D-Bus  1.6.30
dbus-marshal-recursive-util.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-marshal-recursive-util.c  Would be in dbus-marshal-recursive.c, but only used in bus/tests
00003  *
00004  * Copyright (C) 2004, 2005 Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 
00026 #ifdef DBUS_BUILD_TESTS
00027 
00028 #include "dbus-marshal-recursive.h"
00029 #include "dbus-marshal-basic.h"
00030 #include "dbus-signature.h"
00031 #include "dbus-internals.h"
00032 #include <string.h>
00033 
00034 static void
00035 basic_value_zero (DBusBasicValue *value)
00036 {
00037 
00038 #ifdef DBUS_HAVE_INT64
00039   value->u64 = 0;
00040 #else
00041   value->eight.first32 = 0;
00042   value->eight.second32 = 0;
00043 #endif
00044 }
00045 
00046 static dbus_bool_t
00047 basic_value_equal (int             type,
00048                    DBusBasicValue *lhs,
00049                    DBusBasicValue *rhs)
00050 {
00051   if (type == DBUS_TYPE_STRING ||
00052       type == DBUS_TYPE_SIGNATURE ||
00053       type == DBUS_TYPE_OBJECT_PATH)
00054     {
00055       return strcmp (lhs->str, rhs->str) == 0;
00056     }
00057   else
00058     {
00059 #ifdef DBUS_HAVE_INT64
00060       return lhs->u64 == rhs->u64;
00061 #else
00062       return lhs->eight.first32 == rhs->eight.first32 &&
00063         lhs->eight.second32 == rhs->eight.second32;
00064 #endif
00065     }
00066 }
00067 
00068 static dbus_bool_t
00069 equal_values_helper (DBusTypeReader *lhs,
00070                      DBusTypeReader *rhs)
00071 {
00072   int lhs_type;
00073   int rhs_type;
00074 
00075   lhs_type = _dbus_type_reader_get_current_type (lhs);
00076   rhs_type = _dbus_type_reader_get_current_type (rhs);
00077 
00078   if (lhs_type != rhs_type)
00079     return FALSE;
00080 
00081   if (lhs_type == DBUS_TYPE_INVALID)
00082     return TRUE;
00083 
00084   if (dbus_type_is_basic (lhs_type))
00085     {
00086       DBusBasicValue lhs_value;
00087       DBusBasicValue rhs_value;
00088 
00089       basic_value_zero (&lhs_value);
00090       basic_value_zero (&rhs_value);
00091       
00092       _dbus_type_reader_read_basic (lhs, &lhs_value);
00093       _dbus_type_reader_read_basic (rhs, &rhs_value);
00094 
00095       return basic_value_equal (lhs_type, &lhs_value, &rhs_value);
00096     }
00097   else
00098     {
00099       DBusTypeReader lhs_sub;
00100       DBusTypeReader rhs_sub;
00101 
00102       _dbus_type_reader_recurse (lhs, &lhs_sub);
00103       _dbus_type_reader_recurse (rhs, &rhs_sub);
00104 
00105       return equal_values_helper (&lhs_sub, &rhs_sub);
00106     }
00107 }
00108 
00116 dbus_bool_t
00117 _dbus_type_reader_equal_values (const DBusTypeReader *lhs,
00118                                 const DBusTypeReader *rhs)
00119 {
00120   DBusTypeReader copy_lhs = *lhs;
00121   DBusTypeReader copy_rhs = *rhs;
00122 
00123   return equal_values_helper (&copy_lhs, &copy_rhs);
00124 }
00125 
00126 /* TESTS */
00127 
00128 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00129 
00130 #include "dbus-test.h"
00131 #include "dbus-list.h"
00132 #include <stdio.h>
00133 #include <stdlib.h>
00134 
00135 /* Whether to do the OOM stuff (only with other expensive tests) */
00136 #define TEST_OOM_HANDLING 0
00137 /* We do start offset 0 through 9, to get various alignment cases. Still this
00138  * obviously makes the test suite run 10x as slow.
00139  */
00140 #define MAX_INITIAL_OFFSET 9
00141 
00142 /* Largest iteration count to test copying, realignment,
00143  * etc. with. i.e. we only test this stuff with some of the smaller
00144  * data sets.
00145  */
00146 #define MAX_ITERATIONS_FOR_EXPENSIVE_TESTS 1000
00147 
00148 typedef struct
00149 {
00150   int byte_order;
00151   int initial_offset;
00152   DBusString signature;
00153   DBusString body;
00154 } DataBlock;
00155 
00156 typedef struct
00157 {
00158   int saved_sig_len;
00159   int saved_body_len;
00160 } DataBlockState;
00161 
00162 #define N_FENCE_BYTES 5
00163 #define FENCE_BYTES_STR "abcde"
00164 #define INITIAL_PADDING_BYTE '\0'
00165 
00166 static dbus_bool_t
00167 data_block_init (DataBlock *block,
00168                  int        byte_order,
00169                  int        initial_offset)
00170 {
00171   if (!_dbus_string_init (&block->signature))
00172     return FALSE;
00173 
00174   if (!_dbus_string_init (&block->body))
00175     {
00176       _dbus_string_free (&block->signature);
00177       return FALSE;
00178     }
00179 
00180   if (!_dbus_string_insert_bytes (&block->signature, 0, initial_offset,
00181                                   INITIAL_PADDING_BYTE) ||
00182       !_dbus_string_insert_bytes (&block->body, 0, initial_offset,
00183                                   INITIAL_PADDING_BYTE) ||
00184       !_dbus_string_append (&block->signature, FENCE_BYTES_STR) ||
00185       !_dbus_string_append (&block->body, FENCE_BYTES_STR))
00186     {
00187       _dbus_string_free (&block->signature);
00188       _dbus_string_free (&block->body);
00189       return FALSE;
00190     }
00191 
00192   block->byte_order = byte_order;
00193   block->initial_offset = initial_offset;
00194 
00195   return TRUE;
00196 }
00197 
00198 static void
00199 data_block_save (DataBlock      *block,
00200                  DataBlockState *state)
00201 {
00202   state->saved_sig_len = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES;
00203   state->saved_body_len = _dbus_string_get_length (&block->body) - N_FENCE_BYTES;
00204 }
00205 
00206 static void
00207 data_block_restore (DataBlock      *block,
00208                     DataBlockState *state)
00209 {
00210   _dbus_string_delete (&block->signature,
00211                        state->saved_sig_len,
00212                        _dbus_string_get_length (&block->signature) - state->saved_sig_len - N_FENCE_BYTES);
00213   _dbus_string_delete (&block->body,
00214                        state->saved_body_len,
00215                        _dbus_string_get_length (&block->body) - state->saved_body_len - N_FENCE_BYTES);
00216 }
00217 
00218 static void
00219 data_block_verify (DataBlock *block)
00220 {
00221   if (!_dbus_string_ends_with_c_str (&block->signature,
00222                                      FENCE_BYTES_STR))
00223     {
00224       int offset;
00225 
00226       offset = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - 8;
00227       if (offset < 0)
00228         offset = 0;
00229 
00230       _dbus_verbose_bytes_of_string (&block->signature,
00231                                      offset,
00232                                      _dbus_string_get_length (&block->signature) - offset);
00233       _dbus_assert_not_reached ("block did not verify: bad bytes at end of signature");
00234     }
00235   if (!_dbus_string_ends_with_c_str (&block->body,
00236                                      FENCE_BYTES_STR))
00237     {
00238       int offset;
00239 
00240       offset = _dbus_string_get_length (&block->body) - N_FENCE_BYTES - 8;
00241       if (offset < 0)
00242         offset = 0;
00243 
00244       _dbus_verbose_bytes_of_string (&block->body,
00245                                      offset,
00246                                      _dbus_string_get_length (&block->body) - offset);
00247       _dbus_assert_not_reached ("block did not verify: bad bytes at end of body");
00248     }
00249 
00250   _dbus_assert (_dbus_string_validate_nul (&block->signature,
00251                                            0, block->initial_offset));
00252   _dbus_assert (_dbus_string_validate_nul (&block->body,
00253                                            0, block->initial_offset));
00254 }
00255 
00256 static void
00257 data_block_free (DataBlock *block)
00258 {
00259   data_block_verify (block);
00260 
00261   _dbus_string_free (&block->signature);
00262   _dbus_string_free (&block->body);
00263 }
00264 
00265 static void
00266 data_block_reset (DataBlock *block)
00267 {
00268   data_block_verify (block);
00269 
00270   _dbus_string_delete (&block->signature,
00271                        block->initial_offset,
00272                        _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - block->initial_offset);
00273   _dbus_string_delete (&block->body,
00274                        block->initial_offset,
00275                        _dbus_string_get_length (&block->body) - N_FENCE_BYTES - block->initial_offset);
00276 
00277   data_block_verify (block);
00278 }
00279 
00280 static void
00281 data_block_init_reader_writer (DataBlock      *block,
00282                                DBusTypeReader *reader,
00283                                DBusTypeWriter *writer)
00284 {
00285   if (reader)
00286     _dbus_type_reader_init (reader,
00287                             block->byte_order,
00288                             &block->signature,
00289                             block->initial_offset,
00290                             &block->body,
00291                             block->initial_offset);
00292 
00293   if (writer)
00294     _dbus_type_writer_init (writer,
00295                             block->byte_order,
00296                             &block->signature,
00297                             _dbus_string_get_length (&block->signature) - N_FENCE_BYTES,
00298                             &block->body,
00299                             _dbus_string_get_length (&block->body) - N_FENCE_BYTES);
00300 }
00301 
00302 static void
00303 real_check_expected_type (DBusTypeReader *reader,
00304                           int             expected,
00305                           const char     *funcname,
00306                           int             line)
00307 {
00308   int t;
00309 
00310   t = _dbus_type_reader_get_current_type (reader);
00311 
00312   if (t != expected)
00313     {
00314       _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
00315                   _dbus_type_to_string (t),
00316                   _dbus_type_to_string (expected),
00317                   funcname, line);
00318 
00319       _dbus_assert_not_reached ("read wrong type");
00320     }
00321 }
00322 
00323 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
00324 
00325 #define NEXT_EXPECTING_TRUE(reader)  do { if (!_dbus_type_reader_next (reader))         \
00326  {                                                                                      \
00327     _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n",        \
00328                               _DBUS_FUNCTION_NAME, __LINE__);                           \
00329     _dbus_assert_not_reached ("test failed");                                           \
00330  }                                                                                      \
00331 } while (0)
00332 
00333 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader))          \
00334  {                                                                                      \
00335     _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n",       \
00336                               _DBUS_FUNCTION_NAME, __LINE__);                           \
00337     _dbus_assert_not_reached ("test failed");                                           \
00338  }                                                                                      \
00339  check_expected_type (reader, DBUS_TYPE_INVALID);                                       \
00340 } while (0)
00341 
00342 typedef struct TestTypeNode               TestTypeNode;
00343 typedef struct TestTypeNodeClass          TestTypeNodeClass;
00344 typedef struct TestTypeNodeContainer      TestTypeNodeContainer;
00345 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
00346 
00347 struct TestTypeNode
00348 {
00349   const TestTypeNodeClass *klass;
00350 };
00351 
00352 struct TestTypeNodeContainer
00353 {
00354   TestTypeNode base;
00355   DBusList    *children;
00356 };
00357 
00358 struct TestTypeNodeClass
00359 {
00360   int typecode;
00361 
00362   int instance_size;
00363 
00364   int subclass_detail; /* a bad hack to avoid a bunch of subclass casting */
00365 
00366   dbus_bool_t   (* construct)     (TestTypeNode   *node);
00367   void          (* destroy)       (TestTypeNode   *node);
00368 
00369   dbus_bool_t (* write_value)     (TestTypeNode   *node,
00370                                    DataBlock      *block,
00371                                    DBusTypeWriter *writer,
00372                                    int             seed);
00373   dbus_bool_t (* read_value)      (TestTypeNode   *node,
00374                                    DBusTypeReader *reader,
00375                                    int             seed);
00376   dbus_bool_t (* set_value)       (TestTypeNode   *node,
00377                                    DBusTypeReader *reader,
00378                                    DBusTypeReader *realign_root,
00379                                    int             seed);
00380   dbus_bool_t (* build_signature) (TestTypeNode   *node,
00381                                    DBusString     *str);
00382   dbus_bool_t (* write_multi)     (TestTypeNode   *node,
00383                                    DataBlock      *block,
00384                                    DBusTypeWriter *writer,
00385                                    int             seed,
00386                                    int             count);
00387   dbus_bool_t (* read_multi)      (TestTypeNode   *node,
00388                                    DBusTypeReader *reader,
00389                                    int             seed,
00390                                    int             count);
00391 };
00392 
00393 struct TestTypeNodeContainerClass
00394 {
00395   TestTypeNodeClass base;
00396 };
00397 
00398 /* FIXME this could be chilled out substantially by unifying
00399  * the basic types into basic_write_value/basic_read_value
00400  * and by merging read_value and set_value into one function
00401  * taking a flag argument.
00402  */
00403 static dbus_bool_t int16_write_value       (TestTypeNode   *node,
00404                                             DataBlock      *block,
00405                                             DBusTypeWriter *writer,
00406                                             int             seed);
00407 static dbus_bool_t int16_read_value        (TestTypeNode   *node,
00408                                             DBusTypeReader *reader,
00409                                             int             seed);
00410 static dbus_bool_t int16_set_value         (TestTypeNode   *node,
00411                                             DBusTypeReader *reader,
00412                                             DBusTypeReader *realign_root,
00413                                             int             seed);
00414 static dbus_bool_t int16_write_multi       (TestTypeNode   *node,
00415                                             DataBlock      *block,
00416                                             DBusTypeWriter *writer,
00417                                             int             seed,
00418                                             int             count);
00419 static dbus_bool_t int16_read_multi        (TestTypeNode   *node,
00420                                             DBusTypeReader *reader,
00421                                             int             seed,
00422                                             int             count);
00423 static dbus_bool_t int32_write_value       (TestTypeNode   *node,
00424                                             DataBlock      *block,
00425                                             DBusTypeWriter *writer,
00426                                             int             seed);
00427 static dbus_bool_t int32_read_value        (TestTypeNode   *node,
00428                                             DBusTypeReader *reader,
00429                                             int             seed);
00430 static dbus_bool_t int32_set_value         (TestTypeNode   *node,
00431                                             DBusTypeReader *reader,
00432                                             DBusTypeReader *realign_root,
00433                                             int             seed);
00434 static dbus_bool_t int32_write_multi       (TestTypeNode   *node,
00435                                             DataBlock      *block,
00436                                             DBusTypeWriter *writer,
00437                                             int             seed,
00438                                             int             count);
00439 static dbus_bool_t int32_read_multi        (TestTypeNode   *node,
00440                                             DBusTypeReader *reader,
00441                                             int             seed,
00442                                             int             count);
00443 static dbus_bool_t int64_write_value       (TestTypeNode   *node,
00444                                             DataBlock      *block,
00445                                             DBusTypeWriter *writer,
00446                                             int             seed);
00447 static dbus_bool_t int64_read_value        (TestTypeNode   *node,
00448                                             DBusTypeReader *reader,
00449                                             int             seed);
00450 static dbus_bool_t int64_set_value         (TestTypeNode   *node,
00451                                             DBusTypeReader *reader,
00452                                             DBusTypeReader *realign_root,
00453                                             int             seed);
00454 static dbus_bool_t string_write_value      (TestTypeNode   *node,
00455                                             DataBlock      *block,
00456                                             DBusTypeWriter *writer,
00457                                             int             seed);
00458 static dbus_bool_t string_read_value       (TestTypeNode   *node,
00459                                             DBusTypeReader *reader,
00460                                             int             seed);
00461 static dbus_bool_t string_set_value        (TestTypeNode   *node,
00462                                             DBusTypeReader *reader,
00463                                             DBusTypeReader *realign_root,
00464                                             int             seed);
00465 static dbus_bool_t bool_write_value        (TestTypeNode   *node,
00466                                             DataBlock      *block,
00467                                             DBusTypeWriter *writer,
00468                                             int             seed);
00469 static dbus_bool_t bool_read_value         (TestTypeNode   *node,
00470                                             DBusTypeReader *reader,
00471                                             int             seed);
00472 static dbus_bool_t bool_set_value          (TestTypeNode   *node,
00473                                             DBusTypeReader *reader,
00474                                             DBusTypeReader *realign_root,
00475                                             int             seed);
00476 static dbus_bool_t byte_write_value        (TestTypeNode   *node,
00477                                             DataBlock      *block,
00478                                             DBusTypeWriter *writer,
00479                                             int             seed);
00480 static dbus_bool_t byte_read_value         (TestTypeNode   *node,
00481                                             DBusTypeReader *reader,
00482                                             int             seed);
00483 static dbus_bool_t byte_set_value          (TestTypeNode   *node,
00484                                             DBusTypeReader *reader,
00485                                             DBusTypeReader *realign_root,
00486                                             int             seed);
00487 static dbus_bool_t double_write_value      (TestTypeNode   *node,
00488                                             DataBlock      *block,
00489                                             DBusTypeWriter *writer,
00490                                             int             seed);
00491 static dbus_bool_t double_read_value       (TestTypeNode   *node,
00492                                             DBusTypeReader *reader,
00493                                             int             seed);
00494 static dbus_bool_t double_set_value        (TestTypeNode   *node,
00495                                             DBusTypeReader *reader,
00496                                             DBusTypeReader *realign_root,
00497                                             int             seed);
00498 static dbus_bool_t object_path_write_value (TestTypeNode   *node,
00499                                             DataBlock      *block,
00500                                             DBusTypeWriter *writer,
00501                                             int             seed);
00502 static dbus_bool_t object_path_read_value  (TestTypeNode   *node,
00503                                             DBusTypeReader *reader,
00504                                             int             seed);
00505 static dbus_bool_t object_path_set_value   (TestTypeNode   *node,
00506                                             DBusTypeReader *reader,
00507                                             DBusTypeReader *realign_root,
00508                                             int             seed);
00509 static dbus_bool_t signature_write_value   (TestTypeNode   *node,
00510                                             DataBlock      *block,
00511                                             DBusTypeWriter *writer,
00512                                             int             seed);
00513 static dbus_bool_t signature_read_value    (TestTypeNode   *node,
00514                                             DBusTypeReader *reader,
00515                                             int             seed);
00516 static dbus_bool_t signature_set_value     (TestTypeNode   *node,
00517                                             DBusTypeReader *reader,
00518                                             DBusTypeReader *realign_root,
00519                                             int             seed);
00520 static dbus_bool_t struct_write_value      (TestTypeNode   *node,
00521                                             DataBlock      *block,
00522                                             DBusTypeWriter *writer,
00523                                             int             seed);
00524 static dbus_bool_t struct_read_value       (TestTypeNode   *node,
00525                                             DBusTypeReader *reader,
00526                                             int             seed);
00527 static dbus_bool_t struct_set_value        (TestTypeNode   *node,
00528                                             DBusTypeReader *reader,
00529                                             DBusTypeReader *realign_root,
00530                                             int             seed);
00531 static dbus_bool_t struct_build_signature  (TestTypeNode   *node,
00532                                             DBusString     *str);
00533 static dbus_bool_t dict_write_value        (TestTypeNode   *node,
00534                                             DataBlock      *block,
00535                                             DBusTypeWriter *writer,
00536                                             int             seed);
00537 static dbus_bool_t dict_read_value         (TestTypeNode   *node,
00538                                             DBusTypeReader *reader,
00539                                             int             seed);
00540 static dbus_bool_t dict_set_value          (TestTypeNode   *node,
00541                                             DBusTypeReader *reader,
00542                                             DBusTypeReader *realign_root,
00543                                             int             seed);
00544 static dbus_bool_t dict_build_signature    (TestTypeNode   *node,
00545                                             DBusString     *str);
00546 static dbus_bool_t array_write_value       (TestTypeNode   *node,
00547                                             DataBlock      *block,
00548                                             DBusTypeWriter *writer,
00549                                             int             seed);
00550 static dbus_bool_t array_read_value        (TestTypeNode   *node,
00551                                             DBusTypeReader *reader,
00552                                             int             seed);
00553 static dbus_bool_t array_set_value         (TestTypeNode   *node,
00554                                             DBusTypeReader *reader,
00555                                             DBusTypeReader *realign_root,
00556                                             int             seed);
00557 static dbus_bool_t array_build_signature   (TestTypeNode   *node,
00558                                             DBusString     *str);
00559 static dbus_bool_t variant_write_value     (TestTypeNode   *node,
00560                                             DataBlock      *block,
00561                                             DBusTypeWriter *writer,
00562                                             int             seed);
00563 static dbus_bool_t variant_read_value      (TestTypeNode   *node,
00564                                             DBusTypeReader *reader,
00565                                             int             seed);
00566 static dbus_bool_t variant_set_value       (TestTypeNode   *node,
00567                                             DBusTypeReader *reader,
00568                                             DBusTypeReader *realign_root,
00569                                             int             seed);
00570 static void        container_destroy       (TestTypeNode   *node);
00571 
00572 
00573 
00574 static const TestTypeNodeClass int16_class = {
00575   DBUS_TYPE_INT16,
00576   sizeof (TestTypeNode),
00577   0,
00578   NULL,
00579   NULL,
00580   int16_write_value,
00581   int16_read_value,
00582   int16_set_value,
00583   NULL,
00584   int16_write_multi,
00585   int16_read_multi
00586 };
00587 
00588 static const TestTypeNodeClass uint16_class = {
00589   DBUS_TYPE_UINT16,
00590   sizeof (TestTypeNode),
00591   0,
00592   NULL,
00593   NULL,
00594   int16_write_value, /* recycle from int16 */
00595   int16_read_value,  /* recycle from int16 */
00596   int16_set_value,   /* recycle from int16 */
00597   NULL,
00598   int16_write_multi, /* recycle from int16 */
00599   int16_read_multi   /* recycle from int16 */
00600 };
00601 
00602 static const TestTypeNodeClass int32_class = {
00603   DBUS_TYPE_INT32,
00604   sizeof (TestTypeNode),
00605   0,
00606   NULL,
00607   NULL,
00608   int32_write_value,
00609   int32_read_value,
00610   int32_set_value,
00611   NULL,
00612   int32_write_multi,
00613   int32_read_multi
00614 };
00615 
00616 static const TestTypeNodeClass uint32_class = {
00617   DBUS_TYPE_UINT32,
00618   sizeof (TestTypeNode),
00619   0,
00620   NULL,
00621   NULL,
00622   int32_write_value, /* recycle from int32 */
00623   int32_read_value,  /* recycle from int32 */
00624   int32_set_value,   /* recycle from int32 */
00625   NULL,
00626   int32_write_multi, /* recycle from int32 */
00627   int32_read_multi   /* recycle from int32 */
00628 };
00629 
00630 static const TestTypeNodeClass int64_class = {
00631   DBUS_TYPE_INT64,
00632   sizeof (TestTypeNode),
00633   0,
00634   NULL,
00635   NULL,
00636   int64_write_value,
00637   int64_read_value,
00638   int64_set_value,
00639   NULL,
00640   NULL, /* FIXME */
00641   NULL  /* FIXME */
00642 };
00643 
00644 static const TestTypeNodeClass uint64_class = {
00645   DBUS_TYPE_UINT64,
00646   sizeof (TestTypeNode),
00647   0,
00648   NULL,
00649   NULL,
00650   int64_write_value, /* recycle from int64 */
00651   int64_read_value,  /* recycle from int64 */
00652   int64_set_value,   /* recycle from int64 */
00653   NULL,
00654   NULL, /* FIXME */
00655   NULL  /* FIXME */
00656 };
00657 
00658 static const TestTypeNodeClass string_0_class = {
00659   DBUS_TYPE_STRING,
00660   sizeof (TestTypeNode),
00661   0, /* string length */
00662   NULL,
00663   NULL,
00664   string_write_value,
00665   string_read_value,
00666   string_set_value,
00667   NULL,
00668   NULL,
00669   NULL
00670 };
00671 
00672 static const TestTypeNodeClass string_1_class = {
00673   DBUS_TYPE_STRING,
00674   sizeof (TestTypeNode),
00675   1, /* string length */
00676   NULL,
00677   NULL,
00678   string_write_value,
00679   string_read_value,
00680   string_set_value,
00681   NULL,
00682   NULL,
00683   NULL
00684 };
00685 
00686 /* with nul, a len 3 string should fill 4 bytes and thus is "special" */
00687 static const TestTypeNodeClass string_3_class = {
00688   DBUS_TYPE_STRING,
00689   sizeof (TestTypeNode),
00690   3, /* string length */
00691   NULL,
00692   NULL,
00693   string_write_value,
00694   string_read_value,
00695   string_set_value,
00696   NULL,
00697   NULL,
00698   NULL
00699 };
00700 
00701 /* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */
00702 static const TestTypeNodeClass string_8_class = {
00703   DBUS_TYPE_STRING,
00704   sizeof (TestTypeNode),
00705   8, /* string length */
00706   NULL,
00707   NULL,
00708   string_write_value,
00709   string_read_value,
00710   string_set_value,
00711   NULL,
00712   NULL,
00713   NULL
00714 };
00715 
00716 static const TestTypeNodeClass bool_class = {
00717   DBUS_TYPE_BOOLEAN,
00718   sizeof (TestTypeNode),
00719   0,
00720   NULL,
00721   NULL,
00722   bool_write_value,
00723   bool_read_value,
00724   bool_set_value,
00725   NULL,
00726   NULL, /* FIXME */
00727   NULL  /* FIXME */
00728 };
00729 
00730 static const TestTypeNodeClass byte_class = {
00731   DBUS_TYPE_BYTE,
00732   sizeof (TestTypeNode),
00733   0,
00734   NULL,
00735   NULL,
00736   byte_write_value,
00737   byte_read_value,
00738   byte_set_value,
00739   NULL,
00740   NULL, /* FIXME */
00741   NULL  /* FIXME */
00742 };
00743 
00744 static const TestTypeNodeClass double_class = {
00745   DBUS_TYPE_DOUBLE,
00746   sizeof (TestTypeNode),
00747   0,
00748   NULL,
00749   NULL,
00750   double_write_value,
00751   double_read_value,
00752   double_set_value,
00753   NULL,
00754   NULL, /* FIXME */
00755   NULL  /* FIXME */
00756 };
00757 
00758 static const TestTypeNodeClass object_path_class = {
00759   DBUS_TYPE_OBJECT_PATH,
00760   sizeof (TestTypeNode),
00761   0,
00762   NULL,
00763   NULL,
00764   object_path_write_value,
00765   object_path_read_value,
00766   object_path_set_value,
00767   NULL,
00768   NULL,
00769   NULL
00770 };
00771 
00772 static const TestTypeNodeClass signature_class = {
00773   DBUS_TYPE_SIGNATURE,
00774   sizeof (TestTypeNode),
00775   0,
00776   NULL,
00777   NULL,
00778   signature_write_value,
00779   signature_read_value,
00780   signature_set_value,
00781   NULL,
00782   NULL,
00783   NULL
00784 };
00785 
00786 static const TestTypeNodeClass struct_1_class = {
00787   DBUS_TYPE_STRUCT,
00788   sizeof (TestTypeNodeContainer),
00789   1, /* number of times children appear as fields */
00790   NULL,
00791   container_destroy,
00792   struct_write_value,
00793   struct_read_value,
00794   struct_set_value,
00795   struct_build_signature,
00796   NULL,
00797   NULL
00798 };
00799 
00800 static const TestTypeNodeClass struct_2_class = {
00801   DBUS_TYPE_STRUCT,
00802   sizeof (TestTypeNodeContainer),
00803   2, /* number of times children appear as fields */
00804   NULL,
00805   container_destroy,
00806   struct_write_value,
00807   struct_read_value,
00808   struct_set_value,
00809   struct_build_signature,
00810   NULL,
00811   NULL
00812 };
00813 
00814 static const TestTypeNodeClass dict_1_class = {
00815   DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */
00816   sizeof (TestTypeNodeContainer),
00817   1, /* number of entries */
00818   NULL,
00819   container_destroy,
00820   dict_write_value,
00821   dict_read_value,
00822   dict_set_value,
00823   dict_build_signature,
00824   NULL,
00825   NULL
00826 };
00827 
00828 static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;
00829 
00830 static const TestTypeNodeClass array_0_class = {
00831   DBUS_TYPE_ARRAY,
00832   sizeof (TestTypeNodeContainer),
00833   0, /* number of array elements */
00834   NULL,
00835   container_destroy,
00836   array_write_value,
00837   array_read_value,
00838   array_set_value,
00839   array_build_signature,
00840   NULL,
00841   NULL
00842 };
00843 
00844 static const TestTypeNodeClass array_1_class = {
00845   DBUS_TYPE_ARRAY,
00846   sizeof (TestTypeNodeContainer),
00847   1, /* number of array elements */
00848   NULL,
00849   container_destroy,
00850   array_write_value,
00851   array_read_value,
00852   array_set_value,
00853   array_build_signature,
00854   NULL,
00855   NULL
00856 };
00857 
00858 static const TestTypeNodeClass array_2_class = {
00859   DBUS_TYPE_ARRAY,
00860   sizeof (TestTypeNodeContainer),
00861   2, /* number of array elements */
00862   NULL,
00863   container_destroy,
00864   array_write_value,
00865   array_read_value,
00866   array_set_value,
00867   array_build_signature,
00868   NULL,
00869   NULL
00870 };
00871 
00872 static const TestTypeNodeClass array_9_class = {
00873   DBUS_TYPE_ARRAY,
00874   sizeof (TestTypeNodeContainer),
00875   9, /* number of array elements */
00876   NULL,
00877   container_destroy,
00878   array_write_value,
00879   array_read_value,
00880   array_set_value,
00881   array_build_signature,
00882   NULL,
00883   NULL
00884 };
00885 
00886 static const TestTypeNodeClass variant_class = {
00887   DBUS_TYPE_VARIANT,
00888   sizeof (TestTypeNodeContainer),
00889   0,
00890   NULL,
00891   container_destroy,
00892   variant_write_value,
00893   variant_read_value,
00894   variant_set_value,
00895   NULL,
00896   NULL,
00897   NULL
00898 };
00899 
00900 static const TestTypeNodeClass* const
00901 basic_nodes[] = {
00902   &int16_class,
00903   &uint16_class,
00904   &int32_class,
00905   &uint32_class,
00906   &int64_class,
00907   &uint64_class,
00908   &bool_class,
00909   &byte_class,
00910   &double_class,
00911   &string_0_class,
00912   &string_1_class,
00913   &string_3_class,
00914   &string_8_class,
00915   &object_path_class,
00916   &signature_class
00917 };
00918 #define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
00919 
00920 static const TestTypeNodeClass* const
00921 container_nodes[] = {
00922   &struct_1_class,
00923   &array_1_class,
00924   &struct_2_class,
00925   &array_0_class,
00926   &array_2_class,
00927   &variant_class,
00928   &dict_1_class /* last since we want struct and array before it */
00929   /* array_9_class is omitted on purpose, it's too slow;
00930    * we only use it in one hardcoded test below
00931    */
00932 };
00933 #define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
00934 
00935 static TestTypeNode*
00936 node_new (const TestTypeNodeClass *klass)
00937 {
00938   TestTypeNode *node;
00939 
00940   node = dbus_malloc0 (klass->instance_size);
00941   if (node == NULL)
00942     return NULL;
00943 
00944   node->klass = klass;
00945 
00946   if (klass->construct)
00947     {
00948       if (!(* klass->construct) (node))
00949         {
00950           dbus_free (node);
00951           return NULL;
00952         }
00953     }
00954 
00955   return node;
00956 }
00957 
00958 static void
00959 node_destroy (TestTypeNode *node)
00960 {
00961   if (node->klass->destroy)
00962     (* node->klass->destroy) (node);
00963   dbus_free (node);
00964 }
00965 
00966 static dbus_bool_t
00967 node_write_value (TestTypeNode   *node,
00968                   DataBlock      *block,
00969                   DBusTypeWriter *writer,
00970                   int             seed)
00971 {
00972   dbus_bool_t retval;
00973 
00974   retval = (* node->klass->write_value) (node, block, writer, seed);
00975 
00976 #if 0
00977   /* Handy to see where things break, but too expensive to do all the time */
00978   data_block_verify (block);
00979 #endif
00980 
00981   return retval;
00982 }
00983 
00984 static dbus_bool_t
00985 node_read_value (TestTypeNode   *node,
00986                  DBusTypeReader *reader,
00987                  int             seed)
00988 {
00989   /* DBusTypeReader restored; */
00990 
00991   if (!(* node->klass->read_value) (node, reader, seed))
00992     return FALSE;
00993 
00994   return TRUE;
00995 }
00996 
00997 /* Warning: if this one fails due to OOM, it has side effects (can
00998  * modify only some of the sub-values). OK in a test suite, but we
00999  * never do this in real code.
01000  */
01001 static dbus_bool_t
01002 node_set_value (TestTypeNode   *node,
01003                 DBusTypeReader *reader,
01004                 DBusTypeReader *realign_root,
01005                 int             seed)
01006 {
01007   if (!(* node->klass->set_value) (node, reader, realign_root, seed))
01008     return FALSE;
01009 
01010   return TRUE;
01011 }
01012 
01013 static dbus_bool_t
01014 node_build_signature (TestTypeNode *node,
01015                       DBusString   *str)
01016 {
01017   if (node->klass->build_signature)
01018     return (* node->klass->build_signature) (node, str);
01019   else
01020     return _dbus_string_append_byte (str, node->klass->typecode);
01021 }
01022 
01023 static dbus_bool_t
01024 node_append_child (TestTypeNode *node,
01025                    TestTypeNode *child)
01026 {
01027   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01028 
01029   _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
01030 
01031   if (!_dbus_list_append (&container->children, child))
01032     _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 */
01033 
01034   return TRUE;
01035 }
01036 
01037 static dbus_bool_t
01038 node_write_multi (TestTypeNode   *node,
01039                   DataBlock      *block,
01040                   DBusTypeWriter *writer,
01041                   int             seed,
01042                   int             n_copies)
01043 {
01044   dbus_bool_t retval;
01045 
01046   _dbus_assert (node->klass->write_multi != NULL);
01047   retval = (* node->klass->write_multi) (node, block, writer, seed, n_copies);
01048 
01049 #if 0
01050   /* Handy to see where things break, but too expensive to do all the time */
01051   data_block_verify (block);
01052 #endif
01053 
01054   return retval;
01055 }
01056 
01057 static dbus_bool_t
01058 node_read_multi (TestTypeNode   *node,
01059                  DBusTypeReader *reader,
01060                  int             seed,
01061                  int             n_copies)
01062 {
01063   _dbus_assert (node->klass->read_multi != NULL);
01064 
01065   if (!(* node->klass->read_multi) (node, reader, seed, n_copies))
01066     return FALSE;
01067 
01068   return TRUE;
01069 }
01070 
01071 static int n_iterations_completed_total = 0;
01072 static int n_iterations_completed_this_test = 0;
01073 static int n_iterations_expected_this_test = 0;
01074 
01075 typedef struct
01076 {
01077   const DBusString   *signature;
01078   DataBlock          *block;
01079   int                 type_offset;
01080   TestTypeNode      **nodes;
01081   int                 n_nodes;
01082 } NodeIterationData;
01083 
01084 static dbus_bool_t
01085 run_test_copy (NodeIterationData *nid)
01086 {
01087   DataBlock *src;
01088   DataBlock dest;
01089   dbus_bool_t retval;
01090   DBusTypeReader reader;
01091   DBusTypeWriter writer;
01092 
01093   _dbus_verbose ("\n");
01094 
01095   src = nid->block;
01096 
01097   retval = FALSE;
01098 
01099   if (!data_block_init (&dest, src->byte_order, src->initial_offset))
01100     return FALSE;
01101 
01102   data_block_init_reader_writer (src, &reader, NULL);
01103   data_block_init_reader_writer (&dest, NULL, &writer);
01104 
01105   /* DBusTypeWriter assumes it's writing into an existing signature,
01106    * so doesn't add nul on its own. We have to do that.
01107    */
01108   if (!_dbus_string_insert_byte (&dest.signature,
01109                                  dest.initial_offset, '\0'))
01110     goto out;
01111 
01112   if (!_dbus_type_writer_write_reader (&writer, &reader))
01113     goto out;
01114 
01115   /* Data blocks should now be identical */
01116   if (!_dbus_string_equal (&src->signature, &dest.signature))
01117     {
01118       _dbus_verbose ("SOURCE\n");
01119       _dbus_verbose_bytes_of_string (&src->signature, 0,
01120                                      _dbus_string_get_length (&src->signature));
01121       _dbus_verbose ("DEST\n");
01122       _dbus_verbose_bytes_of_string (&dest.signature, 0,
01123                                      _dbus_string_get_length (&dest.signature));
01124       _dbus_assert_not_reached ("signatures did not match");
01125     }
01126 
01127   if (!_dbus_string_equal (&src->body, &dest.body))
01128     {
01129       _dbus_verbose ("SOURCE\n");
01130       _dbus_verbose_bytes_of_string (&src->body, 0,
01131                                      _dbus_string_get_length (&src->body));
01132       _dbus_verbose ("DEST\n");
01133       _dbus_verbose_bytes_of_string (&dest.body, 0,
01134                                      _dbus_string_get_length (&dest.body));
01135       _dbus_assert_not_reached ("bodies did not match");
01136     }
01137 
01138   retval = TRUE;
01139 
01140  out:
01141 
01142   data_block_free (&dest);
01143 
01144   return retval;
01145 }
01146 
01147 static dbus_bool_t
01148 run_test_values_only_write (NodeIterationData *nid)
01149 {
01150   DBusTypeReader reader;
01151   DBusTypeWriter writer;
01152   int i;
01153   dbus_bool_t retval;
01154   int sig_len;
01155 
01156   _dbus_verbose ("\n");
01157 
01158   retval = FALSE;
01159 
01160   data_block_reset (nid->block);
01161 
01162   sig_len = _dbus_string_get_length (nid->signature);
01163 
01164   _dbus_type_writer_init_values_only (&writer,
01165                                       nid->block->byte_order,
01166                                       nid->signature, 0,
01167                                       &nid->block->body,
01168                                       _dbus_string_get_length (&nid->block->body) - N_FENCE_BYTES);
01169   _dbus_type_reader_init (&reader,
01170                           nid->block->byte_order,
01171                           nid->signature, 0,
01172                           &nid->block->body,
01173                           nid->block->initial_offset);
01174 
01175   i = 0;
01176   while (i < nid->n_nodes)
01177     {
01178       if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
01179         goto out;
01180 
01181       ++i;
01182     }
01183 
01184   /* if we wrote any typecodes then this would fail */
01185   _dbus_assert (sig_len == _dbus_string_get_length (nid->signature));
01186 
01187   /* But be sure we wrote out the values correctly */
01188   i = 0;
01189   while (i < nid->n_nodes)
01190     {
01191       if (!node_read_value (nid->nodes[i], &reader, i))
01192         goto out;
01193 
01194       if (i + 1 == nid->n_nodes)
01195         NEXT_EXPECTING_FALSE (&reader);
01196       else
01197         NEXT_EXPECTING_TRUE (&reader);
01198 
01199       ++i;
01200     }
01201 
01202   retval = TRUE;
01203 
01204  out:
01205   data_block_reset (nid->block);
01206   return retval;
01207 }
01208 
01209 /* offset the seed for setting, so we set different numbers than
01210  * we originally wrote. Don't offset by a huge number since in
01211  * some cases it's value = possibilities[seed % n_possibilities]
01212  * and we don't want to wrap around. bool_from_seed
01213  * is just seed % 2 even.
01214  */
01215 #define SET_SEED 1
01216 static dbus_bool_t
01217 run_test_set_values (NodeIterationData *nid)
01218 {
01219   DBusTypeReader reader;
01220   DBusTypeReader realign_root;
01221   dbus_bool_t retval;
01222   int i;
01223 
01224   _dbus_verbose ("\n");
01225 
01226   retval = FALSE;
01227 
01228   data_block_init_reader_writer (nid->block,
01229                                  &reader, NULL);
01230 
01231   realign_root = reader;
01232 
01233   i = 0;
01234   while (i < nid->n_nodes)
01235     {
01236       if (!node_set_value (nid->nodes[i],
01237                            &reader, &realign_root,
01238                            i + SET_SEED))
01239         goto out;
01240 
01241       if (i + 1 == nid->n_nodes)
01242         NEXT_EXPECTING_FALSE (&reader);
01243       else
01244         NEXT_EXPECTING_TRUE (&reader);
01245 
01246       ++i;
01247     }
01248 
01249   /* Check that the new values were set */
01250 
01251   reader = realign_root;
01252 
01253   i = 0;
01254   while (i < nid->n_nodes)
01255     {
01256       if (!node_read_value (nid->nodes[i], &reader,
01257                             i + SET_SEED))
01258         goto out;
01259 
01260       if (i + 1 == nid->n_nodes)
01261         NEXT_EXPECTING_FALSE (&reader);
01262       else
01263         NEXT_EXPECTING_TRUE (&reader);
01264 
01265       ++i;
01266     }
01267 
01268   retval = TRUE;
01269 
01270  out:
01271   return retval;
01272 }
01273 
01274 static dbus_bool_t
01275 run_test_delete_values (NodeIterationData *nid)
01276 {
01277   DBusTypeReader reader;
01278   dbus_bool_t retval;
01279   int t;
01280 
01281   _dbus_verbose ("\n");
01282 
01283   retval = FALSE;
01284 
01285   data_block_init_reader_writer (nid->block,
01286                                  &reader, NULL);
01287 
01288   while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
01289     {
01290       /* Right now, deleting only works on array elements.  We delete
01291        * all array elements, and then verify that there aren't any
01292        * left.
01293        */
01294       if (t == DBUS_TYPE_ARRAY)
01295         {
01296           DBusTypeReader array;
01297           int n_elements;
01298           int elem_type;
01299 
01300           _dbus_type_reader_recurse (&reader, &array);
01301           n_elements = 0;
01302           while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
01303             {
01304               n_elements += 1;
01305               _dbus_type_reader_next (&array);
01306             }
01307 
01308           /* reset to start of array */
01309           _dbus_type_reader_recurse (&reader, &array);
01310           _dbus_verbose ("recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d\n",
01311                          reader.value_pos, array.value_pos, array.u.array.start_pos);
01312           while ((elem_type = _dbus_type_reader_get_current_type (&array)) != DBUS_TYPE_INVALID)
01313             {
01314               /* We don't want to always delete from the same part of the array. */
01315               static int cycle = 0;
01316               int elem;
01317 
01318               _dbus_assert (n_elements > 0);
01319 
01320               elem = cycle;
01321               if (elem == 3 || elem >= n_elements) /* end of array */
01322                 elem = n_elements - 1;
01323 
01324               _dbus_verbose ("deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d\n",
01325                              elem, n_elements, _dbus_type_to_string (elem_type),
01326                              cycle, reader.value_pos, array.value_pos);
01327               while (elem > 0)
01328                 {
01329                   if (!_dbus_type_reader_next (&array))
01330                     _dbus_assert_not_reached ("should have had another element\n");
01331                   --elem;
01332                 }
01333 
01334               if (!_dbus_type_reader_delete (&array, &reader))
01335                 goto out;
01336 
01337               n_elements -= 1;
01338 
01339               /* reset */
01340               _dbus_type_reader_recurse (&reader, &array);
01341 
01342               if (cycle > 2)
01343                 cycle = 0;
01344               else
01345                 cycle += 1;
01346             }
01347         }
01348       _dbus_type_reader_next (&reader);
01349     }
01350 
01351   /* Check that there are no array elements left */
01352   data_block_init_reader_writer (nid->block,
01353                                  &reader, NULL);
01354 
01355   while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
01356     {
01357       _dbus_type_reader_next (&reader);
01358     }
01359 
01360   retval = TRUE;
01361 
01362  out:
01363   return retval;
01364 }
01365 
01366 static dbus_bool_t
01367 run_test_nodes_iteration (void *data)
01368 {
01369   NodeIterationData *nid = data;
01370   DBusTypeReader reader;
01371   DBusTypeWriter writer;
01372   int i;
01373   dbus_bool_t retval;
01374 
01375   /* Stuff to do:
01376    * 1. write the value
01377    * 2. strcmp-compare with the signature we built
01378    * 3. read the value
01379    * 4. type-iterate the signature and the value and see if they are the same type-wise
01380    */
01381   retval = FALSE;
01382 
01383   data_block_init_reader_writer (nid->block,
01384                                  &reader, &writer);
01385 
01386   /* DBusTypeWriter assumes it's writing into an existing signature,
01387    * so doesn't add nul on its own. We have to do that.
01388    */
01389   if (!_dbus_string_insert_byte (&nid->block->signature,
01390                                  nid->type_offset, '\0'))
01391     goto out;
01392 
01393   i = 0;
01394   while (i < nid->n_nodes)
01395     {
01396       if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
01397         goto out;
01398 
01399       ++i;
01400     }
01401 
01402   if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
01403                                      &nid->block->signature, nid->type_offset))
01404     {
01405       _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
01406                   _dbus_string_get_const_data (nid->signature),
01407                   _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
01408                   nid->type_offset);
01409       _dbus_assert_not_reached ("wrong signature");
01410     }
01411 
01412   i = 0;
01413   while (i < nid->n_nodes)
01414     {
01415       if (!node_read_value (nid->nodes[i], &reader, i))
01416         goto out;
01417 
01418       if (i + 1 == nid->n_nodes)
01419         NEXT_EXPECTING_FALSE (&reader);
01420       else
01421         NEXT_EXPECTING_TRUE (&reader);
01422 
01423       ++i;
01424     }
01425 
01426   if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
01427     {
01428       /* this set values test uses code from copy and
01429        * values_only_write so would ideally be last so you get a
01430        * simpler test case for problems with copying or values_only
01431        * writing; but it also needs an already-written DataBlock so it
01432        * has to go first. Comment it out if it breaks, and see if the
01433        * later tests also break - debug them first if so.
01434        */
01435       if (!run_test_set_values (nid))
01436         goto out;
01437 
01438       if (!run_test_delete_values (nid))
01439         goto out;
01440 
01441       if (!run_test_copy (nid))
01442         goto out;
01443 
01444       if (!run_test_values_only_write (nid))
01445         goto out;
01446     }
01447 
01448   /* FIXME type-iterate both signature and value and compare the resulting
01449    * tree to the node tree perhaps
01450    */
01451 
01452   retval = TRUE;
01453 
01454  out:
01455 
01456   data_block_reset (nid->block);
01457 
01458   return retval;
01459 }
01460 
01461 static void
01462 run_test_nodes_in_one_configuration (TestTypeNode    **nodes,
01463                                      int               n_nodes,
01464                                      const DBusString *signature,
01465                                      int               byte_order,
01466                                      int               initial_offset)
01467 {
01468   DataBlock block;
01469   NodeIterationData nid;
01470 
01471   if (!data_block_init (&block, byte_order, initial_offset))
01472     _dbus_assert_not_reached ("no memory");
01473 
01474   nid.signature = signature;
01475   nid.block = &block;
01476   nid.type_offset = initial_offset;
01477   nid.nodes = nodes;
01478   nid.n_nodes = n_nodes;
01479 
01480   if (TEST_OOM_HANDLING &&
01481       n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
01482     {
01483       _dbus_test_oom_handling ("running test node",
01484                                run_test_nodes_iteration,
01485                                &nid);
01486     }
01487   else
01488     {
01489       if (!run_test_nodes_iteration (&nid))
01490         _dbus_assert_not_reached ("no memory");
01491     }
01492 
01493   data_block_free (&block);
01494 }
01495 
01496 static void
01497 run_test_nodes (TestTypeNode **nodes,
01498                 int            n_nodes)
01499 {
01500   int i;
01501   DBusString signature;
01502 
01503   if (!_dbus_string_init (&signature))
01504     _dbus_assert_not_reached ("no memory");
01505 
01506   i = 0;
01507   while (i < n_nodes)
01508     {
01509       if (! node_build_signature (nodes[i], &signature))
01510         _dbus_assert_not_reached ("no memory");
01511 
01512       ++i;
01513     }
01514 
01515   _dbus_verbose (">>> test nodes with signature '%s'\n",
01516                  _dbus_string_get_const_data (&signature));
01517 
01518   i = 0;
01519   while (i <= MAX_INITIAL_OFFSET)
01520     {
01521       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
01522                                            DBUS_LITTLE_ENDIAN, i);
01523       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
01524                                            DBUS_BIG_ENDIAN, i);
01525 
01526       ++i;
01527     }
01528 
01529   n_iterations_completed_this_test += 1;
01530   n_iterations_completed_total += 1;
01531 
01532   if (n_iterations_completed_this_test == n_iterations_expected_this_test)
01533     {
01534       fprintf (stderr, " 100%% %d this test (%d cumulative)\n",
01535                n_iterations_completed_this_test,
01536                n_iterations_completed_total);
01537     }
01538   /* this happens to turn out well with mod == 1 */
01539   else if ((n_iterations_completed_this_test %
01540             (int)(n_iterations_expected_this_test / 10.0)) == 1)
01541     {
01542       fprintf (stderr, " %d%% ", (int) (n_iterations_completed_this_test / (double) n_iterations_expected_this_test * 100));
01543     }
01544 
01545   _dbus_string_free (&signature);
01546 }
01547 
01548 #define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
01549 
01550 static TestTypeNode*
01551 value_generator (int *ip)
01552 {
01553   int i = *ip;
01554   const TestTypeNodeClass *child_klass;
01555   const TestTypeNodeClass *container_klass;
01556   TestTypeNode *child;
01557   TestTypeNode *node;
01558 
01559   _dbus_assert (i <= N_VALUES);
01560 
01561   if (i == N_VALUES)
01562     {
01563       return NULL;
01564     }
01565   else if (i < N_BASICS)
01566     {
01567       node = node_new (basic_nodes[i]);
01568     }
01569   else
01570     {
01571       /* imagine an array:
01572        * container 0 of basic 0
01573        * container 0 of basic 1
01574        * container 0 of basic 2
01575        * container 1 of basic 0
01576        * container 1 of basic 1
01577        * container 1 of basic 2
01578        */
01579       i -= N_BASICS;
01580 
01581       container_klass = container_nodes[i / N_BASICS];
01582       child_klass = basic_nodes[i % N_BASICS];
01583 
01584       node = node_new (container_klass);
01585       child = node_new (child_klass);
01586 
01587       node_append_child (node, child);
01588     }
01589 
01590   *ip += 1; /* increment the generator */
01591 
01592   return node;
01593 }
01594 
01595 static void
01596 build_body (TestTypeNode **nodes,
01597             int            n_nodes,
01598             int            byte_order,
01599             DBusString    *signature,
01600             DBusString    *body)
01601 {
01602   int i;
01603   DataBlock block;
01604   DBusTypeReader reader;
01605   DBusTypeWriter writer;
01606 
01607   i = 0;
01608   while (i < n_nodes)
01609     {
01610       if (! node_build_signature (nodes[i], signature))
01611         _dbus_assert_not_reached ("no memory");
01612       
01613       ++i;
01614     }
01615 
01616   if (!data_block_init (&block, byte_order, 0))
01617     _dbus_assert_not_reached ("no memory");
01618   
01619   data_block_init_reader_writer (&block,
01620                                  &reader, &writer);
01621   
01622   /* DBusTypeWriter assumes it's writing into an existing signature,
01623    * so doesn't add nul on its own. We have to do that.
01624    */
01625   if (!_dbus_string_insert_byte (&block.signature,
01626                                  0, '\0'))
01627     _dbus_assert_not_reached ("no memory");
01628 
01629   i = 0;
01630   while (i < n_nodes)
01631     {
01632       if (!node_write_value (nodes[i], &block, &writer, i))
01633         _dbus_assert_not_reached ("no memory");
01634 
01635       ++i;
01636     }
01637 
01638   if (!_dbus_string_copy_len (&block.body, 0,
01639                               _dbus_string_get_length (&block.body) - N_FENCE_BYTES,
01640                               body, 0))
01641     _dbus_assert_not_reached ("oom");
01642 
01643   data_block_free (&block);  
01644 }
01645 
01646 dbus_bool_t
01647 dbus_internal_do_not_use_generate_bodies (int           sequence,
01648                                           int           byte_order,
01649                                           DBusString   *signature,
01650                                           DBusString   *body)
01651 {
01652   TestTypeNode *nodes[1];
01653   int i;
01654   int n_nodes;
01655 
01656   nodes[0] = value_generator (&sequence);
01657 
01658   if (nodes[0] == NULL)
01659     return FALSE;
01660 
01661   n_nodes = 1;
01662   
01663   build_body (nodes, n_nodes, byte_order, signature, body);
01664 
01665 
01666   i = 0;
01667   while (i < n_nodes)
01668     {
01669       node_destroy (nodes[i]);
01670       ++i;
01671     }
01672   
01673   return TRUE;
01674 }
01675 
01676 static void
01677 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
01678                                       int                      n_nested)
01679 {
01680   TestTypeNode *root;
01681   TestTypeNode *container;
01682   TestTypeNode *child;
01683   int i;
01684 
01685   root = node_new (container_klass);
01686   container = root;
01687   for (i = 1; i < n_nested; i++)
01688     {
01689       child = node_new (container_klass);
01690       node_append_child (container, child);
01691       container = child;
01692     }
01693 
01694   /* container should now be the most-nested container */
01695 
01696   i = 0;
01697   while ((child = value_generator (&i)))
01698     {
01699       node_append_child (container, child);
01700 
01701       run_test_nodes (&root, 1);
01702 
01703       _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
01704       node_destroy (child);
01705     }
01706 
01707   node_destroy (root);
01708 }
01709 
01710 static void
01711 start_next_test (const char *format,
01712                  int         expected)
01713 {
01714   n_iterations_completed_this_test = 0;
01715   n_iterations_expected_this_test = expected;
01716 
01717   fprintf (stderr, ">>> >>> ");
01718   fprintf (stderr, format,
01719            n_iterations_expected_this_test);
01720 }
01721 
01722 static void
01723 make_and_run_test_nodes (void)
01724 {
01725   int i, j, k, m;
01726 
01727   /* We try to do this in order of "complicatedness" so that test
01728    * failures tend to show up in the simplest test case that
01729    * demonstrates the failure.  There are also some tests that run
01730    * more than once for this reason, first while going through simple
01731    * cases, second while going through a broader range of complex
01732    * cases.
01733    */
01734   /* Each basic node. The basic nodes should include:
01735    *
01736    * - each fixed-size type (in such a way that it has different values each time,
01737    *                         so we can tell if we mix two of them up)
01738    * - strings of various lengths
01739    * - object path
01740    * - signature
01741    */
01742   /* Each container node. The container nodes should include:
01743    *
01744    *  struct with 1 and 2 copies of the contained item
01745    *  array with 0, 1, 2 copies of the contained item
01746    *  variant
01747    */
01748   /*  Let a "value" be a basic node, or a container containing a single basic node.
01749    *  Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
01750    *  When iterating through all values to make combinations, do the basic types
01751    *  first and the containers second.
01752    */
01753   /* Each item is shown with its number of iterations to complete so
01754    * we can keep a handle on this unit test
01755    */
01756 
01757   /* FIXME test just an empty body, no types at all */
01758 
01759   start_next_test ("Each value by itself %d iterations\n", N_VALUES);
01760   {
01761     TestTypeNode *node;
01762     i = 0;
01763     while ((node = value_generator (&i)))
01764       {
01765         run_test_nodes (&node, 1);
01766 
01767         node_destroy (node);
01768       }
01769   }
01770 
01771   start_next_test ("Each value by itself with arrays as blocks %d iterations\n", N_VALUES);
01772   arrays_write_fixed_in_blocks = TRUE;
01773   {
01774     TestTypeNode *node;
01775     i = 0;
01776     while ((node = value_generator (&i)))
01777       {
01778         run_test_nodes (&node, 1);
01779 
01780         node_destroy (node);
01781       }
01782   }
01783   arrays_write_fixed_in_blocks = FALSE;
01784 
01785   start_next_test ("All values in one big toplevel %d iteration\n", 1);
01786   {
01787     TestTypeNode *nodes[N_VALUES];
01788     TestTypeNode *node;
01789 
01790     i = 0;
01791     while ((node = value_generator (&i)))
01792       {
01793         nodes[i - 1] = node;
01794       }
01795 
01796     run_test_nodes (nodes, N_VALUES);
01797 
01798     for (i = 0; i < N_VALUES; i++)
01799       node_destroy (nodes[i]);
01800   }
01801 
01802   start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n",
01803                    N_VALUES * N_VALUES);
01804   {
01805     TestTypeNode *nodes[2];
01806 
01807     i = 0;
01808     while ((nodes[0] = value_generator (&i)))
01809       {
01810         j = 0;
01811         while ((nodes[1] = value_generator (&j)))
01812           {
01813             run_test_nodes (nodes, 2);
01814 
01815             node_destroy (nodes[1]);
01816           }
01817 
01818         node_destroy (nodes[0]);
01819       }
01820   }
01821 
01822   start_next_test ("Each container containing each value %d iterations\n",
01823                    N_CONTAINERS * N_VALUES);
01824   for (i = 0; i < N_CONTAINERS; i++)
01825     {
01826       const TestTypeNodeClass *container_klass = container_nodes[i];
01827 
01828       make_and_run_values_inside_container (container_klass, 1);
01829     }
01830 
01831   start_next_test ("Each container containing each value with arrays as blocks %d iterations\n",
01832                    N_CONTAINERS * N_VALUES);
01833   arrays_write_fixed_in_blocks = TRUE;
01834   for (i = 0; i < N_CONTAINERS; i++)
01835     {
01836       const TestTypeNodeClass *container_klass = container_nodes[i];
01837 
01838       make_and_run_values_inside_container (container_klass, 1);
01839     }
01840   arrays_write_fixed_in_blocks = FALSE;
01841 
01842   start_next_test ("Each container of same container of each value %d iterations\n",
01843                    N_CONTAINERS * N_VALUES);
01844   for (i = 0; i < N_CONTAINERS; i++)
01845     {
01846       const TestTypeNodeClass *container_klass = container_nodes[i];
01847 
01848       make_and_run_values_inside_container (container_klass, 2);
01849     }
01850 
01851   start_next_test ("Each container of same container of same container of each value %d iterations\n",
01852                    N_CONTAINERS * N_VALUES);
01853   for (i = 0; i < N_CONTAINERS; i++)
01854     {
01855       const TestTypeNodeClass *container_klass = container_nodes[i];
01856 
01857       make_and_run_values_inside_container (container_klass, 3);
01858     }
01859 
01860   start_next_test ("Each value,value pair inside a struct %d iterations\n",
01861                    N_VALUES * N_VALUES);
01862   {
01863     TestTypeNode *val1, *val2;
01864     TestTypeNode *node;
01865 
01866     node = node_new (&struct_1_class);
01867 
01868     i = 0;
01869     while ((val1 = value_generator (&i)))
01870       {
01871         j = 0;
01872         while ((val2 = value_generator (&j)))
01873           {
01874             TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01875 
01876             node_append_child (node, val1);
01877             node_append_child (node, val2);
01878 
01879             run_test_nodes (&node, 1);
01880 
01881             _dbus_list_clear (&container->children);
01882             node_destroy (val2);
01883           }
01884         node_destroy (val1);
01885       }
01886     node_destroy (node);
01887   }
01888 
01889   start_next_test ("All values in one big struct %d iteration\n",
01890                    1);
01891   {
01892     TestTypeNode *node;
01893     TestTypeNode *child;
01894 
01895     node = node_new (&struct_1_class);
01896 
01897     i = 0;
01898     while ((child = value_generator (&i)))
01899       node_append_child (node, child);
01900 
01901     run_test_nodes (&node, 1);
01902 
01903     node_destroy (node);
01904   }
01905 
01906   start_next_test ("Each value in a large array %d iterations\n",
01907                    N_VALUES);
01908   {
01909     TestTypeNode *val;
01910     TestTypeNode *node;
01911 
01912     node = node_new (&array_9_class);
01913 
01914     i = 0;
01915     while ((val = value_generator (&i)))
01916       {
01917         TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01918 
01919         node_append_child (node, val);
01920 
01921         run_test_nodes (&node, 1);
01922 
01923         _dbus_list_clear (&container->children);
01924         node_destroy (val);
01925       }
01926 
01927     node_destroy (node);
01928   }
01929 
01930   if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
01931       atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
01932     {
01933       fprintf (stderr, "skipping remaining marshal-recursive tests, "
01934           "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
01935       goto out;
01936     }
01937 
01938   start_next_test ("Each container of each container of each value %d iterations\n",
01939                    N_CONTAINERS * N_CONTAINERS * N_VALUES);
01940   for (i = 0; i < N_CONTAINERS; i++)
01941     {
01942       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
01943       TestTypeNode *outer_container = node_new (outer_container_klass);
01944 
01945       for (j = 0; j < N_CONTAINERS; j++)
01946         {
01947           TestTypeNode *child;
01948           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
01949           TestTypeNode *inner_container = node_new (inner_container_klass);
01950 
01951           node_append_child (outer_container, inner_container);
01952 
01953           m = 0;
01954           while ((child = value_generator (&m)))
01955             {
01956               node_append_child (inner_container, child);
01957 
01958               run_test_nodes (&outer_container, 1);
01959 
01960               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
01961               node_destroy (child);
01962             }
01963           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
01964           node_destroy (inner_container);
01965         }
01966       node_destroy (outer_container);
01967     }
01968 
01969   start_next_test ("Each container of each container of each container of each value %d iterations\n",
01970                    N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
01971   for (i = 0; i < N_CONTAINERS; i++)
01972     {
01973       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
01974       TestTypeNode *outer_container = node_new (outer_container_klass);
01975 
01976       for (j = 0; j < N_CONTAINERS; j++)
01977         {
01978           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
01979           TestTypeNode *inner_container = node_new (inner_container_klass);
01980 
01981           node_append_child (outer_container, inner_container);
01982 
01983           for (k = 0; k < N_CONTAINERS; k++)
01984             {
01985               TestTypeNode *child;
01986               const TestTypeNodeClass *center_container_klass = container_nodes[k];
01987               TestTypeNode *center_container = node_new (center_container_klass);
01988 
01989               node_append_child (inner_container, center_container);
01990 
01991               m = 0;
01992               while ((child = value_generator (&m)))
01993                 {
01994                   node_append_child (center_container, child);
01995 
01996                   run_test_nodes (&outer_container, 1);
01997 
01998                   _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
01999                   node_destroy (child);
02000                 }
02001               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
02002               node_destroy (center_container);
02003             }
02004           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
02005           node_destroy (inner_container);
02006         }
02007       node_destroy (outer_container);
02008     }
02009 
02010   /* This one takes a really long time (10 minutes on a Core2), so only enable
02011    * it if you're really sure */
02012   if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
02013     {
02014       fprintf (stderr, "skipping really slow marshal-recursive test, "
02015           "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
02016       goto out;
02017     }
02018 
02019   start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
02020                    N_VALUES * N_VALUES * N_VALUES);
02021   {
02022     TestTypeNode *nodes[3];
02023 
02024     i = 0;
02025     while ((nodes[0] = value_generator (&i)))
02026       {
02027         j = 0;
02028         while ((nodes[1] = value_generator (&j)))
02029           {
02030             k = 0;
02031             while ((nodes[2] = value_generator (&k)))
02032               {
02033                 run_test_nodes (nodes, 3);
02034 
02035                 node_destroy (nodes[2]);
02036               }
02037             node_destroy (nodes[1]);
02038           }
02039         node_destroy (nodes[0]);
02040       }
02041   }
02042 
02043 out:
02044   fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
02045            n_iterations_completed_total);
02046   fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
02047            MAX_INITIAL_OFFSET);
02048   fprintf (stderr, "out of memory handling %s tested\n",
02049            TEST_OOM_HANDLING ? "was" : "was not");
02050 }
02051 
02052 dbus_bool_t
02053 _dbus_marshal_recursive_test (void)
02054 {
02055   make_and_run_test_nodes ();
02056 
02057   return TRUE;
02058 }
02059 
02060 /*
02061  *
02062  *
02063  *         Implementations of each type node class
02064  *
02065  *
02066  *
02067  */
02068 #define MAX_MULTI_COUNT 5
02069 
02070 #define SAMPLE_INT16           1234
02071 #define SAMPLE_INT16_ALTERNATE 6785
02072 static dbus_int16_t
02073 int16_from_seed (int seed)
02074 {
02075   /* Generate an integer value that's predictable from seed.  We could
02076    * just use seed itself, but that would only ever touch one byte of
02077    * the int so would miss some kinds of bug.
02078    */
02079   dbus_int16_t v;
02080 
02081   v = 42; /* just to quiet compiler afaik */
02082   switch (seed % 5)
02083     {
02084     case 0:
02085       v = SAMPLE_INT16;
02086       break;
02087     case 1:
02088       v = SAMPLE_INT16_ALTERNATE;
02089       break;
02090     case 2:
02091       v = -1;
02092       break;
02093     case 3:
02094       v = _DBUS_INT16_MAX;
02095       break;
02096     case 4:
02097       v = 1;
02098       break;
02099     }
02100 
02101   if (seed > 1)
02102     v *= seed; /* wraps around eventually, which is fine */
02103 
02104   return v;
02105 }
02106 
02107 static dbus_bool_t
02108 int16_write_value (TestTypeNode   *node,
02109                    DataBlock      *block,
02110                    DBusTypeWriter *writer,
02111                    int             seed)
02112 {
02113   /* also used for uint16 */
02114   dbus_int16_t v;
02115 
02116   v = int16_from_seed (seed);
02117 
02118   return _dbus_type_writer_write_basic (writer,
02119                                         node->klass->typecode,
02120                                         &v);
02121 }
02122 
02123 static dbus_bool_t
02124 int16_read_value (TestTypeNode   *node,
02125                   DBusTypeReader *reader,
02126                   int             seed)
02127 {
02128   /* also used for uint16 */
02129   dbus_int16_t v;
02130 
02131   check_expected_type (reader, node->klass->typecode);
02132 
02133   _dbus_type_reader_read_basic (reader,
02134                                 (dbus_int16_t*) &v);
02135 
02136   _dbus_assert (v == int16_from_seed (seed));
02137 
02138   return TRUE;
02139 }
02140 
02141 static dbus_bool_t
02142 int16_set_value (TestTypeNode   *node,
02143                  DBusTypeReader *reader,
02144                  DBusTypeReader *realign_root,
02145                  int             seed)
02146 {
02147   /* also used for uint16 */
02148   dbus_int16_t v;
02149 
02150   v = int16_from_seed (seed);
02151 
02152   return _dbus_type_reader_set_basic (reader,
02153                                       &v,
02154                                       realign_root);
02155 }
02156 
02157 static dbus_bool_t
02158 int16_write_multi (TestTypeNode   *node,
02159                    DataBlock      *block,
02160                    DBusTypeWriter *writer,
02161                    int             seed,
02162                    int             count)
02163 {
02164   /* also used for uint16 */
02165   dbus_int16_t values[MAX_MULTI_COUNT];
02166   dbus_int16_t *v_ARRAY_INT16 = values;
02167   int i;
02168 
02169   for (i = 0; i < count; ++i)
02170     values[i] = int16_from_seed (seed + i);
02171 
02172   return _dbus_type_writer_write_fixed_multi (writer,
02173                                               node->klass->typecode,
02174                                               &v_ARRAY_INT16, count);
02175 }
02176 
02177 static dbus_bool_t
02178 int16_read_multi (TestTypeNode   *node,
02179                   DBusTypeReader *reader,
02180                   int             seed,
02181                   int             count)
02182 {
02183   /* also used for uint16 */
02184   dbus_int16_t *values;
02185   int n_elements;
02186   int i;
02187 
02188   check_expected_type (reader, node->klass->typecode);
02189 
02190   _dbus_type_reader_read_fixed_multi (reader,
02191                                       &values,
02192                                       &n_elements);
02193 
02194   if (n_elements != count)
02195     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
02196   _dbus_assert (n_elements == count);
02197 
02198   for (i = 0; i < count; i++)
02199     _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
02200                                                       (const unsigned char*)values + (i * 2))) ==
02201                   int16_from_seed (seed + i));
02202 
02203   return TRUE;
02204 }
02205 
02206 
02207 #define SAMPLE_INT32           12345678
02208 #define SAMPLE_INT32_ALTERNATE 53781429
02209 static dbus_int32_t
02210 int32_from_seed (int seed)
02211 {
02212   /* Generate an integer value that's predictable from seed.  We could
02213    * just use seed itself, but that would only ever touch one byte of
02214    * the int so would miss some kinds of bug.
02215    */
02216   dbus_int32_t v;
02217 
02218   v = 42; /* just to quiet compiler afaik */
02219   switch (seed % 5)
02220     {
02221     case 0:
02222       v = SAMPLE_INT32;
02223       break;
02224     case 1:
02225       v = SAMPLE_INT32_ALTERNATE;
02226       break;
02227     case 2:
02228       v = -1;
02229       break;
02230     case 3:
02231       v = _DBUS_INT_MAX;
02232       break;
02233     case 4:
02234       v = 1;
02235       break;
02236     }
02237 
02238   if (seed > 1)
02239     v *= seed; /* wraps around eventually, which is fine */
02240 
02241   return v;
02242 }
02243 
02244 static dbus_bool_t
02245 int32_write_value (TestTypeNode   *node,
02246                    DataBlock      *block,
02247                    DBusTypeWriter *writer,
02248                    int             seed)
02249 {
02250   /* also used for uint32 */
02251   dbus_int32_t v;
02252 
02253   v = int32_from_seed (seed);
02254 
02255   return _dbus_type_writer_write_basic (writer,
02256                                         node->klass->typecode,
02257                                         &v);
02258 }
02259 
02260 static dbus_bool_t
02261 int32_read_value (TestTypeNode   *node,
02262                   DBusTypeReader *reader,
02263                   int             seed)
02264 {
02265   /* also used for uint32 */
02266   dbus_int32_t v;
02267 
02268   check_expected_type (reader, node->klass->typecode);
02269 
02270   _dbus_type_reader_read_basic (reader,
02271                                 (dbus_int32_t*) &v);
02272 
02273   _dbus_assert (v == int32_from_seed (seed));
02274 
02275   return TRUE;
02276 }
02277 
02278 static dbus_bool_t
02279 int32_set_value (TestTypeNode   *node,
02280                  DBusTypeReader *reader,
02281                  DBusTypeReader *realign_root,
02282                  int             seed)
02283 {
02284   /* also used for uint32 */
02285   dbus_int32_t v;
02286 
02287   v = int32_from_seed (seed);
02288 
02289   return _dbus_type_reader_set_basic (reader,
02290                                       &v,
02291                                       realign_root);
02292 }
02293 
02294 static dbus_bool_t
02295 int32_write_multi (TestTypeNode   *node,
02296                    DataBlock      *block,
02297                    DBusTypeWriter *writer,
02298                    int             seed,
02299                    int             count)
02300 {
02301   /* also used for uint32 */
02302   dbus_int32_t values[MAX_MULTI_COUNT];
02303   dbus_int32_t *v_ARRAY_INT32 = values;
02304   int i;
02305 
02306   for (i = 0; i < count; ++i)
02307     values[i] = int32_from_seed (seed + i);
02308 
02309   return _dbus_type_writer_write_fixed_multi (writer,
02310                                               node->klass->typecode,
02311                                               &v_ARRAY_INT32, count);
02312 }
02313 
02314 static dbus_bool_t
02315 int32_read_multi (TestTypeNode   *node,
02316                   DBusTypeReader *reader,
02317                   int             seed,
02318                   int             count)
02319 {
02320   /* also used for uint32 */
02321   dbus_int32_t *values;
02322   int n_elements;
02323   int i;
02324 
02325   check_expected_type (reader, node->klass->typecode);
02326 
02327   _dbus_type_reader_read_fixed_multi (reader,
02328                                       &values,
02329                                       &n_elements);
02330 
02331   if (n_elements != count)
02332     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
02333   _dbus_assert (n_elements == count);
02334 
02335   for (i = 0; i < count; i++)
02336     _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order,
02337                                              (const unsigned char*)values + (i * 4))) ==
02338                   int32_from_seed (seed + i));
02339 
02340   return TRUE;
02341 }
02342 
02343 #ifdef DBUS_HAVE_INT64
02344 static dbus_int64_t
02345 int64_from_seed (int seed)
02346 {
02347   dbus_int32_t v32;
02348   dbus_int64_t v;
02349 
02350   v32 = int32_from_seed (seed);
02351 
02352   v = - (dbus_int32_t) ~ v32;
02353   v |= (((dbus_int64_t)v32) << 32);
02354 
02355   return v;
02356 }
02357 #endif
02358 
02359 static dbus_bool_t
02360 int64_write_value (TestTypeNode   *node,
02361                    DataBlock      *block,
02362                    DBusTypeWriter *writer,
02363                    int             seed)
02364 {
02365 #ifdef DBUS_HAVE_INT64
02366   /* also used for uint64 */
02367   dbus_int64_t v;
02368 
02369   v = int64_from_seed (seed);
02370 
02371   return _dbus_type_writer_write_basic (writer,
02372                                         node->klass->typecode,
02373                                         &v);
02374 #else
02375   return TRUE;
02376 #endif
02377 }
02378 
02379 static dbus_bool_t
02380 int64_read_value (TestTypeNode   *node,
02381                   DBusTypeReader *reader,
02382                   int             seed)
02383 {
02384 #ifdef DBUS_HAVE_INT64
02385   /* also used for uint64 */
02386   dbus_int64_t v;
02387 
02388   check_expected_type (reader, node->klass->typecode);
02389 
02390   _dbus_type_reader_read_basic (reader,
02391                                 (dbus_int64_t*) &v);
02392 
02393   _dbus_assert (v == int64_from_seed (seed));
02394 
02395   return TRUE;
02396 #else
02397   return TRUE;
02398 #endif
02399 }
02400 
02401 static dbus_bool_t
02402 int64_set_value (TestTypeNode   *node,
02403                  DBusTypeReader *reader,
02404                  DBusTypeReader *realign_root,
02405                  int             seed)
02406 {
02407 #ifdef DBUS_HAVE_INT64
02408   /* also used for uint64 */
02409   dbus_int64_t v;
02410 
02411   v = int64_from_seed (seed);
02412 
02413   return _dbus_type_reader_set_basic (reader,
02414                                       &v,
02415                                       realign_root);
02416 #else
02417   return TRUE;
02418 #endif
02419 }
02420 
02421 #define MAX_SAMPLE_STRING_LEN 10
02422 static void
02423 string_from_seed (char *buf,
02424                   int   len,
02425                   int   seed)
02426 {
02427   int i;
02428   unsigned char v;
02429 
02430   _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
02431 
02432   /* vary the length slightly, though we also have multiple string
02433    * value types for this, varying it here tests the set_value code
02434    */
02435   switch (seed % 3)
02436     {
02437     case 1:
02438       len += 2;
02439       break;
02440     case 2:
02441       len -= 2;
02442       break;
02443     }
02444   if (len < 0)
02445     len = 0;
02446 
02447   v = (unsigned char) ('A' + seed);
02448 
02449   i = 0;
02450   while (i < len)
02451     {
02452       if (v < 'A' || v > 'z')
02453         v = 'A';
02454 
02455       buf[i] = v;
02456 
02457       v += 1;
02458       ++i;
02459     }
02460 
02461   buf[i] = '\0';
02462 }
02463 
02464 static dbus_bool_t
02465 string_write_value (TestTypeNode   *node,
02466                     DataBlock      *block,
02467                     DBusTypeWriter *writer,
02468                     int             seed)
02469 {
02470   char buf[MAX_SAMPLE_STRING_LEN + 1]="";
02471   const char *v_string = buf;
02472 
02473 
02474   string_from_seed (buf, node->klass->subclass_detail,
02475                     seed);
02476 
02477   return _dbus_type_writer_write_basic (writer,
02478                                         node->klass->typecode,
02479                                         &v_string);
02480 }
02481 
02482 static dbus_bool_t
02483 string_read_value (TestTypeNode   *node,
02484                    DBusTypeReader *reader,
02485                    int             seed)
02486 {
02487   const char *v;
02488   char buf[MAX_SAMPLE_STRING_LEN + 1];
02489   v = buf;
02490 
02491   check_expected_type (reader, node->klass->typecode);
02492 
02493   _dbus_type_reader_read_basic (reader,
02494                                 (const char **) &v);
02495 
02496   string_from_seed (buf, node->klass->subclass_detail,
02497                     seed);
02498 
02499   if (strcmp (buf, v) != 0)
02500     {
02501       _dbus_warn ("read string '%s' expected '%s'\n",
02502                   v, buf);
02503       _dbus_assert_not_reached ("test failed");
02504     }
02505 
02506   return TRUE;
02507 }
02508 
02509 static dbus_bool_t
02510 string_set_value (TestTypeNode   *node,
02511                   DBusTypeReader *reader,
02512                   DBusTypeReader *realign_root,
02513                   int             seed)
02514 {
02515   char buf[MAX_SAMPLE_STRING_LEN + 1];
02516   const char *v_string = buf;
02517 
02518   string_from_seed (buf, node->klass->subclass_detail,
02519                     seed);
02520 
02521 #if RECURSIVE_MARSHAL_WRITE_TRACE
02522  {
02523    const char *old;
02524    _dbus_type_reader_read_basic (reader, &old);
02525    _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
02526                   v_string, strlen (v_string), old, strlen (old));
02527  }
02528 #endif
02529 
02530   return _dbus_type_reader_set_basic (reader,
02531                                       &v_string,
02532                                       realign_root);
02533 }
02534 
02535 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
02536 
02537 static dbus_bool_t
02538 bool_write_value (TestTypeNode   *node,
02539                   DataBlock      *block,
02540                   DBusTypeWriter *writer,
02541                   int             seed)
02542 {
02543   dbus_bool_t v;
02544 
02545   v = BOOL_FROM_SEED (seed);
02546 
02547   return _dbus_type_writer_write_basic (writer,
02548                                         node->klass->typecode,
02549                                         &v);
02550 }
02551 
02552 static dbus_bool_t
02553 bool_read_value (TestTypeNode   *node,
02554                  DBusTypeReader *reader,
02555                  int             seed)
02556 {
02557   dbus_bool_t v;
02558 
02559   check_expected_type (reader, node->klass->typecode);
02560 
02561   _dbus_type_reader_read_basic (reader,
02562                                 (unsigned char*) &v);
02563 
02564   _dbus_assert (v == BOOL_FROM_SEED (seed));
02565 
02566   return TRUE;
02567 }
02568 
02569 static dbus_bool_t
02570 bool_set_value (TestTypeNode   *node,
02571                 DBusTypeReader *reader,
02572                 DBusTypeReader *realign_root,
02573                 int             seed)
02574 {
02575   dbus_bool_t v;
02576 
02577   v = BOOL_FROM_SEED (seed);
02578 
02579   return _dbus_type_reader_set_basic (reader,
02580                                       &v,
02581                                       realign_root);
02582 }
02583 
02584 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
02585 
02586 static dbus_bool_t
02587 byte_write_value (TestTypeNode   *node,
02588                   DataBlock      *block,
02589                   DBusTypeWriter *writer,
02590                   int             seed)
02591 {
02592   unsigned char v;
02593 
02594   v = BYTE_FROM_SEED (seed);
02595 
02596   return _dbus_type_writer_write_basic (writer,
02597                                         node->klass->typecode,
02598                                         &v);
02599 }
02600 
02601 static dbus_bool_t
02602 byte_read_value (TestTypeNode   *node,
02603                  DBusTypeReader *reader,
02604                  int             seed)
02605 {
02606   unsigned char v;
02607 
02608   check_expected_type (reader, node->klass->typecode);
02609 
02610   _dbus_type_reader_read_basic (reader,
02611                                 (unsigned char*) &v);
02612 
02613   _dbus_assert (v == BYTE_FROM_SEED (seed));
02614 
02615   return TRUE;
02616 }
02617 
02618 
02619 static dbus_bool_t
02620 byte_set_value (TestTypeNode   *node,
02621                 DBusTypeReader *reader,
02622                 DBusTypeReader *realign_root,
02623                 int             seed)
02624 {
02625   unsigned char v;
02626 
02627   v = BYTE_FROM_SEED (seed);
02628 
02629   return _dbus_type_reader_set_basic (reader,
02630                                       &v,
02631                                       realign_root);
02632 }
02633 
02634 static double
02635 double_from_seed (int seed)
02636 {
02637   return SAMPLE_INT32 * (double) seed + 0.3;
02638 }
02639 
02640 static dbus_bool_t
02641 double_write_value (TestTypeNode   *node,
02642                     DataBlock      *block,
02643                     DBusTypeWriter *writer,
02644                     int             seed)
02645 {
02646   double v;
02647 
02648   v = double_from_seed (seed);
02649 
02650   return _dbus_type_writer_write_basic (writer,
02651                                         node->klass->typecode,
02652                                         &v);
02653 }
02654 
02655 static dbus_bool_t
02656 double_read_value (TestTypeNode   *node,
02657                    DBusTypeReader *reader,
02658                    int             seed)
02659 {
02660   double v;
02661   double expected;
02662 
02663   check_expected_type (reader, node->klass->typecode);
02664 
02665   _dbus_type_reader_read_basic (reader,
02666                                 (double*) &v);
02667 
02668   expected = double_from_seed (seed);
02669 
02670   if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
02671     {
02672 #ifdef DBUS_INT64_PRINTF_MODIFIER
02673       _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",
02674                   expected, v,
02675                   *(dbus_uint64_t*)(char*)&expected,
02676                   *(dbus_uint64_t*)(char*)&v);
02677 #endif
02678       _dbus_assert_not_reached ("test failed");
02679     }
02680 
02681   return TRUE;
02682 }
02683 
02684 static dbus_bool_t
02685 double_set_value (TestTypeNode   *node,
02686                 DBusTypeReader *reader,
02687                 DBusTypeReader *realign_root,
02688                 int             seed)
02689 {
02690   double v;
02691 
02692   v = double_from_seed (seed);
02693 
02694   return _dbus_type_reader_set_basic (reader,
02695                                       &v,
02696                                       realign_root);
02697 }
02698 
02699 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
02700 static void
02701 object_path_from_seed (char *buf,
02702                        int   seed)
02703 {
02704   int i;
02705   unsigned char v;
02706   int len;
02707 
02708   len = seed % 9;
02709   _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
02710 
02711   v = (unsigned char) ('A' + seed);
02712 
02713   if (len < 2)
02714     {
02715       buf[0] = '/';
02716       i = 1;
02717     }
02718   else
02719     {
02720       i = 0;
02721       while (i + 1 < len)
02722         {
02723           if (v < 'A' || v > 'z')
02724             v = 'A';
02725 
02726           buf[i] = '/';
02727           ++i;
02728           buf[i] = v;
02729           ++i;
02730           
02731           v += 1;
02732         }
02733     }
02734 
02735   buf[i] = '\0';
02736 }
02737 
02738 static dbus_bool_t
02739 object_path_write_value (TestTypeNode   *node,
02740                          DataBlock      *block,
02741                          DBusTypeWriter *writer,
02742                          int             seed)
02743 {
02744   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02745   const char *v_string = buf;
02746 
02747   object_path_from_seed (buf, seed);
02748 
02749   return _dbus_type_writer_write_basic (writer,
02750                                         node->klass->typecode,
02751                                         &v_string);
02752 }
02753 
02754 static dbus_bool_t
02755 object_path_read_value (TestTypeNode   *node,
02756                         DBusTypeReader *reader,
02757                         int             seed)
02758 {
02759   const char *v;
02760   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02761 
02762   check_expected_type (reader, node->klass->typecode);
02763 
02764   _dbus_type_reader_read_basic (reader,
02765                                 (const char **) &v);
02766 
02767   object_path_from_seed (buf, seed);
02768 
02769   if (strcmp (buf, v) != 0)
02770     {
02771       _dbus_warn ("read object path '%s' expected '%s'\n",
02772                   v, buf);
02773       _dbus_assert_not_reached ("test failed");
02774     }
02775 
02776   return TRUE;
02777 }
02778 
02779 static dbus_bool_t
02780 object_path_set_value (TestTypeNode   *node,
02781                        DBusTypeReader *reader,
02782                        DBusTypeReader *realign_root,
02783                        int             seed)
02784 {
02785   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02786   const char *v_string = buf;
02787 
02788   object_path_from_seed (buf, seed);
02789 
02790   return _dbus_type_reader_set_basic (reader,
02791                                       &v_string,
02792                                       realign_root);
02793 }
02794 
02795 #define MAX_SAMPLE_SIGNATURE_LEN 10
02796 static void
02797 signature_from_seed (char *buf,
02798                      int   seed)
02799 {
02800   /* try to avoid ascending, descending, or alternating length to help find bugs */
02801   const char *sample_signatures[] = {
02802     "asax"
02803     "",
02804     "asau(xxxx)",
02805     "x",
02806     "ai",
02807     "a(ii)"
02808   };
02809 
02810   strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
02811 }
02812 
02813 static dbus_bool_t
02814 signature_write_value (TestTypeNode   *node,
02815                        DataBlock      *block,
02816                        DBusTypeWriter *writer,
02817                        int             seed)
02818 {
02819   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02820   const char *v_string = buf;
02821 
02822   signature_from_seed (buf, seed);
02823 
02824   return _dbus_type_writer_write_basic (writer,
02825                                         node->klass->typecode,
02826                                         &v_string);
02827 }
02828 
02829 static dbus_bool_t
02830 signature_read_value (TestTypeNode   *node,
02831                       DBusTypeReader *reader,
02832                       int             seed)
02833 {
02834   const char *v;
02835   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02836 
02837   check_expected_type (reader, node->klass->typecode);
02838 
02839   _dbus_type_reader_read_basic (reader,
02840                                 (const char **) &v);
02841 
02842   signature_from_seed (buf, seed);
02843 
02844   if (strcmp (buf, v) != 0)
02845     {
02846       _dbus_warn ("read signature value '%s' expected '%s'\n",
02847                   v, buf);
02848       _dbus_assert_not_reached ("test failed");
02849     }
02850 
02851   return TRUE;
02852 }
02853 
02854 
02855 static dbus_bool_t
02856 signature_set_value (TestTypeNode   *node,
02857                      DBusTypeReader *reader,
02858                      DBusTypeReader *realign_root,
02859                      int             seed)
02860 {
02861   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02862   const char *v_string = buf;
02863 
02864   signature_from_seed (buf, seed);
02865 
02866   return _dbus_type_reader_set_basic (reader,
02867                                       &v_string,
02868                                       realign_root);
02869 }
02870 
02871 static dbus_bool_t
02872 struct_write_value (TestTypeNode   *node,
02873                     DataBlock      *block,
02874                     DBusTypeWriter *writer,
02875                     int             seed)
02876 {
02877   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02878   DataBlockState saved;
02879   DBusTypeWriter sub;
02880   int i;
02881   int n_copies;
02882 
02883   n_copies = node->klass->subclass_detail;
02884 
02885   _dbus_assert (container->children != NULL);
02886 
02887   data_block_save (block, &saved);
02888 
02889   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
02890                                   NULL, 0,
02891                                   &sub))
02892     return FALSE;
02893 
02894   i = 0;
02895   while (i < n_copies)
02896     {
02897       DBusList *link;
02898 
02899       link = _dbus_list_get_first_link (&container->children);
02900       while (link != NULL)
02901         {
02902           TestTypeNode *child = link->data;
02903           DBusList *next = _dbus_list_get_next_link (&container->children, link);
02904 
02905           if (!node_write_value (child, block, &sub, seed + i))
02906             {
02907               data_block_restore (block, &saved);
02908               return FALSE;
02909             }
02910 
02911           link = next;
02912         }
02913 
02914       ++i;
02915     }
02916 
02917   if (!_dbus_type_writer_unrecurse (writer, &sub))
02918     {
02919       data_block_restore (block, &saved);
02920       return FALSE;
02921     }
02922 
02923   return TRUE;
02924 }
02925 
02926 static dbus_bool_t
02927 struct_read_or_set_value (TestTypeNode   *node,
02928                           DBusTypeReader *reader,
02929                           DBusTypeReader *realign_root,
02930                           int             seed)
02931 {
02932   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02933   DBusTypeReader sub;
02934   int i;
02935   int n_copies;
02936 
02937   n_copies = node->klass->subclass_detail;
02938 
02939   check_expected_type (reader, DBUS_TYPE_STRUCT);
02940 
02941   _dbus_type_reader_recurse (reader, &sub);
02942 
02943   i = 0;
02944   while (i < n_copies)
02945     {
02946       DBusList *link;
02947 
02948       link = _dbus_list_get_first_link (&container->children);
02949       while (link != NULL)
02950         {
02951           TestTypeNode *child = link->data;
02952           DBusList *next = _dbus_list_get_next_link (&container->children, link);
02953 
02954           if (realign_root == NULL)
02955             {
02956               if (!node_read_value (child, &sub, seed + i))
02957                 return FALSE;
02958             }
02959           else
02960             {
02961               if (!node_set_value (child, &sub, realign_root, seed + i))
02962                 return FALSE;
02963             }
02964 
02965           if (i == (n_copies - 1) && next == NULL)
02966             NEXT_EXPECTING_FALSE (&sub);
02967           else
02968             NEXT_EXPECTING_TRUE (&sub);
02969 
02970           link = next;
02971         }
02972 
02973       ++i;
02974     }
02975 
02976   return TRUE;
02977 }
02978 
02979 static dbus_bool_t
02980 struct_read_value (TestTypeNode   *node,
02981                    DBusTypeReader *reader,
02982                    int             seed)
02983 {
02984   return struct_read_or_set_value (node, reader, NULL, seed);
02985 }
02986 
02987 static dbus_bool_t
02988 struct_set_value (TestTypeNode   *node,
02989                   DBusTypeReader *reader,
02990                   DBusTypeReader *realign_root,
02991                   int             seed)
02992 {
02993   return struct_read_or_set_value (node, reader, realign_root, seed);
02994 }
02995 
02996 static dbus_bool_t
02997 struct_build_signature (TestTypeNode   *node,
02998                         DBusString     *str)
02999 {
03000   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03001   int i;
03002   int orig_len;
03003   int n_copies;
03004 
03005   n_copies = node->klass->subclass_detail;
03006 
03007   orig_len = _dbus_string_get_length (str);
03008 
03009   if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
03010     goto oom;
03011 
03012   i = 0;
03013   while (i < n_copies)
03014     {
03015       DBusList *link;
03016 
03017       link = _dbus_list_get_first_link (&container->children);
03018       while (link != NULL)
03019         {
03020           TestTypeNode *child = link->data;
03021           DBusList *next = _dbus_list_get_next_link (&container->children, link);
03022 
03023           if (!node_build_signature (child, str))
03024             goto oom;
03025 
03026           link = next;
03027         }
03028 
03029       ++i;
03030     }
03031 
03032   if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
03033     goto oom;
03034 
03035   return TRUE;
03036 
03037  oom:
03038   _dbus_string_set_length (str, orig_len);
03039   return FALSE;
03040 }
03041 
03042 static dbus_bool_t
03043 array_write_value (TestTypeNode   *node,
03044                    DataBlock      *block,
03045                    DBusTypeWriter *writer,
03046                    int             seed)
03047 {
03048   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03049   DataBlockState saved;
03050   DBusTypeWriter sub;
03051   DBusString element_signature;
03052   int i;
03053   int n_copies;
03054   int element_type;
03055   TestTypeNode *child;
03056 
03057   n_copies = node->klass->subclass_detail;
03058 
03059   _dbus_assert (container->children != NULL);
03060 
03061   data_block_save (block, &saved);
03062 
03063   if (!_dbus_string_init (&element_signature))
03064     return FALSE;
03065 
03066   child = _dbus_list_get_first (&container->children);
03067 
03068   if (!node_build_signature (child,
03069                              &element_signature))
03070     goto oom;
03071 
03072   element_type = _dbus_first_type_in_signature (&element_signature, 0);
03073 
03074   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
03075                                   &element_signature, 0,
03076                                   &sub))
03077     goto oom;
03078 
03079   if (arrays_write_fixed_in_blocks &&
03080       dbus_type_is_fixed (element_type) &&
03081       child->klass->write_multi)
03082     {
03083       if (!node_write_multi (child, block, &sub, seed, n_copies))
03084         goto oom;
03085     }
03086   else
03087     {
03088       i = 0;
03089       while (i < n_copies)
03090         {
03091           DBusList *link;
03092 
03093           link = _dbus_list_get_first_link (&container->children);
03094           while (link != NULL)
03095             {
03096               TestTypeNode *child = link->data;
03097               DBusList *next = _dbus_list_get_next_link (&container->children, link);
03098 
03099               if (!node_write_value (child, block, &sub, seed + i))
03100                 goto oom;
03101 
03102               link = next;
03103             }
03104 
03105           ++i;
03106         }
03107     }
03108 
03109   if (!_dbus_type_writer_unrecurse (writer, &sub))
03110     goto oom;
03111 
03112   _dbus_string_free (&element_signature);
03113   return TRUE;
03114 
03115  oom:
03116   data_block_restore (block, &saved);
03117   _dbus_string_free (&element_signature);
03118   return FALSE;
03119 }
03120 
03121 static dbus_bool_t
03122 array_read_or_set_value (TestTypeNode   *node,
03123                          DBusTypeReader *reader,
03124                          DBusTypeReader *realign_root,
03125                          int             seed)
03126 {
03127   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03128   DBusTypeReader sub;
03129   int i;
03130   int n_copies;
03131   TestTypeNode *child;
03132 
03133   n_copies = node->klass->subclass_detail;
03134 
03135   check_expected_type (reader, DBUS_TYPE_ARRAY);
03136 
03137   child = _dbus_list_get_first (&container->children);
03138 
03139   if (n_copies > 0)
03140     {
03141       _dbus_type_reader_recurse (reader, &sub);
03142 
03143       if (realign_root == NULL && arrays_write_fixed_in_blocks &&
03144           dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
03145           child->klass->read_multi)
03146         {
03147           if (!node_read_multi (child, &sub, seed, n_copies))
03148             return FALSE;
03149         }
03150       else
03151         {
03152           i = 0;
03153           while (i < n_copies)
03154             {
03155               DBusList *link;
03156 
03157               link = _dbus_list_get_first_link (&container->children);
03158               while (link != NULL)
03159                 {
03160                   TestTypeNode *child = link->data;
03161                   DBusList *next = _dbus_list_get_next_link (&container->children, link);
03162 
03163                   _dbus_assert (child->klass->typecode ==
03164                                 _dbus_type_reader_get_element_type (reader));
03165 
03166                   if (realign_root == NULL)
03167                     {
03168                       if (!node_read_value (child, &sub, seed + i))
03169                         return FALSE;
03170                     }
03171                   else
03172                     {
03173                       if (!node_set_value (child, &sub, realign_root, seed + i))
03174                         return FALSE;
03175                     }
03176 
03177                   if (i == (n_copies - 1) && next == NULL)
03178                     NEXT_EXPECTING_FALSE (&sub);
03179                   else
03180                     NEXT_EXPECTING_TRUE (&sub);
03181 
03182                   link = next;
03183                 }
03184 
03185               ++i;
03186             }
03187         }
03188     }
03189 
03190   return TRUE;
03191 }
03192 
03193 static dbus_bool_t
03194 array_read_value (TestTypeNode   *node,
03195                   DBusTypeReader *reader,
03196                   int             seed)
03197 {
03198   return array_read_or_set_value (node, reader, NULL, seed);
03199 }
03200 
03201 static dbus_bool_t
03202 array_set_value (TestTypeNode   *node,
03203                  DBusTypeReader *reader,
03204                  DBusTypeReader *realign_root,
03205                  int             seed)
03206 {
03207   return array_read_or_set_value (node, reader, realign_root, seed);
03208 }
03209 
03210 static dbus_bool_t
03211 array_build_signature (TestTypeNode   *node,
03212                        DBusString     *str)
03213 {
03214   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03215   int orig_len;
03216 
03217   orig_len = _dbus_string_get_length (str);
03218 
03219   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
03220     goto oom;
03221 
03222   if (!node_build_signature (_dbus_list_get_first (&container->children),
03223                              str))
03224     goto oom;
03225 
03226   return TRUE;
03227 
03228  oom:
03229   _dbus_string_set_length (str, orig_len);
03230   return FALSE;
03231 }
03232 
03233  /* 10 is random just to add another seed that we use in the suite */
03234 #define VARIANT_SEED 10
03235 
03236 static dbus_bool_t
03237 variant_write_value (TestTypeNode   *node,
03238                      DataBlock      *block,
03239                      DBusTypeWriter *writer,
03240                      int             seed)
03241 {
03242   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03243   DataBlockState saved;
03244   DBusTypeWriter sub;
03245   DBusString content_signature;
03246   TestTypeNode *child;
03247 
03248   _dbus_assert (container->children != NULL);
03249   _dbus_assert (_dbus_list_length_is_one (&container->children));
03250 
03251   child = _dbus_list_get_first (&container->children);
03252 
03253   data_block_save (block, &saved);
03254 
03255   if (!_dbus_string_init (&content_signature))
03256     return FALSE;
03257 
03258   if (!node_build_signature (child,
03259                              &content_signature))
03260     goto oom;
03261 
03262   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
03263                                   &content_signature, 0,
03264                                   &sub))
03265     goto oom;
03266 
03267   if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
03268     goto oom;
03269 
03270   if (!_dbus_type_writer_unrecurse (writer, &sub))
03271     goto oom;
03272 
03273   _dbus_string_free (&content_signature);
03274   return TRUE;
03275 
03276  oom:
03277   data_block_restore (block, &saved);
03278   _dbus_string_free (&content_signature);
03279   return FALSE;
03280 }
03281 
03282 static dbus_bool_t
03283 variant_read_or_set_value (TestTypeNode   *node,
03284                            DBusTypeReader *reader,
03285                            DBusTypeReader *realign_root,
03286                            int             seed)
03287 {
03288   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03289   DBusTypeReader sub;
03290   TestTypeNode *child;
03291 
03292   _dbus_assert (container->children != NULL);
03293   _dbus_assert (_dbus_list_length_is_one (&container->children));
03294 
03295   child = _dbus_list_get_first (&container->children);
03296 
03297   check_expected_type (reader, DBUS_TYPE_VARIANT);
03298 
03299   _dbus_type_reader_recurse (reader, &sub);
03300 
03301   if (realign_root == NULL)
03302     {
03303       if (!node_read_value (child, &sub, seed + VARIANT_SEED))
03304         return FALSE;
03305     }
03306   else
03307     {
03308       if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
03309         return FALSE;
03310     }
03311 
03312   NEXT_EXPECTING_FALSE (&sub);
03313 
03314   return TRUE;
03315 }
03316 
03317 static dbus_bool_t
03318 variant_read_value (TestTypeNode   *node,
03319                     DBusTypeReader *reader,
03320                     int             seed)
03321 {
03322   return variant_read_or_set_value (node, reader, NULL, seed);
03323 }
03324 
03325 static dbus_bool_t
03326 variant_set_value (TestTypeNode   *node,
03327                    DBusTypeReader *reader,
03328                    DBusTypeReader *realign_root,
03329                    int             seed)
03330 {
03331   return variant_read_or_set_value (node, reader, realign_root, seed);
03332 }
03333 
03334 static dbus_bool_t
03335 dict_write_value (TestTypeNode   *node,
03336                   DataBlock      *block,
03337                   DBusTypeWriter *writer,
03338                   int             seed)
03339 {
03340   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03341   DataBlockState saved;
03342   DBusTypeWriter sub;
03343   DBusString entry_value_signature;
03344   DBusString dict_entry_signature;
03345   int i;
03346   int n_entries;
03347   TestTypeNode *child;
03348 
03349   n_entries = node->klass->subclass_detail;
03350 
03351   _dbus_assert (container->children != NULL);
03352 
03353   data_block_save (block, &saved);
03354 
03355   if (!_dbus_string_init (&entry_value_signature))
03356     return FALSE;
03357 
03358   if (!_dbus_string_init (&dict_entry_signature))
03359     {
03360       _dbus_string_free (&entry_value_signature);
03361       return FALSE;
03362     }
03363   
03364   child = _dbus_list_get_first (&container->children);
03365 
03366   if (!node_build_signature (child,
03367                              &entry_value_signature))
03368     goto oom;
03369 
03370   if (!_dbus_string_append (&dict_entry_signature,
03371                             DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
03372                             DBUS_TYPE_INT32_AS_STRING))
03373     goto oom;
03374 
03375   if (!_dbus_string_copy (&entry_value_signature, 0,
03376                           &dict_entry_signature,
03377                           _dbus_string_get_length (&dict_entry_signature)))
03378     goto oom;
03379 
03380   if (!_dbus_string_append_byte (&dict_entry_signature,
03381                                  DBUS_DICT_ENTRY_END_CHAR))
03382     goto oom;
03383 
03384   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
03385                                   &dict_entry_signature, 0,
03386                                   &sub))
03387     goto oom;
03388 
03389   i = 0;
03390   while (i < n_entries)
03391     {
03392       DBusTypeWriter entry_sub;
03393       dbus_int32_t key;
03394 
03395       if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
03396                                       NULL, 0,
03397                                       &entry_sub))
03398         goto oom;
03399 
03400       key = int32_from_seed (seed + i);
03401 
03402       if (!_dbus_type_writer_write_basic (&entry_sub,
03403                                           DBUS_TYPE_INT32,
03404                                           &key))
03405         goto oom;
03406       
03407       if (!node_write_value (child, block, &entry_sub, seed + i))
03408         goto oom;
03409 
03410       if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
03411         goto oom;
03412       
03413       ++i;
03414     }
03415 
03416   if (!_dbus_type_writer_unrecurse (writer, &sub))
03417     goto oom;
03418   
03419   _dbus_string_free (&entry_value_signature);
03420   _dbus_string_free (&dict_entry_signature);
03421   return TRUE;
03422 
03423  oom:
03424   data_block_restore (block, &saved);
03425   _dbus_string_free (&entry_value_signature);
03426   _dbus_string_free (&dict_entry_signature);
03427   return FALSE;
03428 }
03429 
03430 static dbus_bool_t
03431 dict_read_or_set_value (TestTypeNode   *node,
03432                         DBusTypeReader *reader,
03433                         DBusTypeReader *realign_root,
03434                         int             seed)
03435 {
03436   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03437   DBusTypeReader sub;
03438   int i;
03439   int n_entries;
03440   TestTypeNode *child;
03441 
03442   n_entries = node->klass->subclass_detail;
03443 
03444   check_expected_type (reader, DBUS_TYPE_ARRAY);
03445 
03446   child = _dbus_list_get_first (&container->children);
03447 
03448   if (n_entries > 0)
03449     {
03450       _dbus_type_reader_recurse (reader, &sub);
03451 
03452       check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
03453       
03454       i = 0;
03455       while (i < n_entries)
03456         {
03457           DBusTypeReader entry_sub;
03458 
03459           check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
03460           
03461           _dbus_type_reader_recurse (&sub, &entry_sub);
03462           
03463           if (realign_root == NULL)
03464             {
03465               dbus_int32_t v;
03466               
03467               check_expected_type (&entry_sub, DBUS_TYPE_INT32);
03468 
03469               _dbus_type_reader_read_basic (&entry_sub,
03470                                             (dbus_int32_t*) &v);
03471 
03472               _dbus_assert (v == int32_from_seed (seed + i));
03473 
03474               NEXT_EXPECTING_TRUE (&entry_sub);
03475               
03476               if (!node_read_value (child, &entry_sub, seed + i))
03477                 return FALSE;
03478 
03479               NEXT_EXPECTING_FALSE (&entry_sub);
03480             }
03481           else
03482             {
03483               dbus_int32_t v;
03484               
03485               v = int32_from_seed (seed + i);
03486               
03487               if (!_dbus_type_reader_set_basic (&entry_sub,
03488                                                 &v,
03489                                                 realign_root))
03490                 return FALSE;
03491 
03492               NEXT_EXPECTING_TRUE (&entry_sub);
03493               
03494               if (!node_set_value (child, &entry_sub, realign_root, seed + i))
03495                 return FALSE;
03496 
03497               NEXT_EXPECTING_FALSE (&entry_sub);
03498             }
03499           
03500           if (i == (n_entries - 1))
03501             NEXT_EXPECTING_FALSE (&sub);
03502           else
03503             NEXT_EXPECTING_TRUE (&sub);
03504 
03505           ++i;
03506         }
03507     }
03508 
03509   return TRUE;
03510 }
03511 
03512 static dbus_bool_t
03513 dict_read_value (TestTypeNode   *node,
03514                  DBusTypeReader *reader,
03515                  int             seed)
03516 {
03517   return dict_read_or_set_value (node, reader, NULL, seed);
03518 }
03519 
03520 static dbus_bool_t
03521 dict_set_value (TestTypeNode   *node,
03522                 DBusTypeReader *reader,
03523                 DBusTypeReader *realign_root,
03524                 int             seed)
03525 {
03526   return dict_read_or_set_value (node, reader, realign_root, seed);
03527 }
03528 
03529 static dbus_bool_t
03530 dict_build_signature (TestTypeNode   *node,
03531                       DBusString     *str)
03532 {
03533   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03534   int orig_len;
03535 
03536   orig_len = _dbus_string_get_length (str);
03537 
03538   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
03539     goto oom;
03540 
03541   if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
03542     goto oom;
03543   
03544   if (!node_build_signature (_dbus_list_get_first (&container->children),
03545                              str))
03546     goto oom;
03547 
03548   if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
03549     goto oom;
03550 
03551   return TRUE;
03552 
03553  oom:
03554   _dbus_string_set_length (str, orig_len);
03555   return FALSE;
03556 }
03557 
03558 static void
03559 container_destroy (TestTypeNode *node)
03560 {
03561   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03562   DBusList *link;
03563 
03564   link = _dbus_list_get_first_link (&container->children);
03565   while (link != NULL)
03566     {
03567       TestTypeNode *child = link->data;
03568       DBusList *next = _dbus_list_get_next_link (&container->children, link);
03569 
03570       node_destroy (child);
03571 
03572       _dbus_list_free_link (link);
03573 
03574       link = next;
03575     }
03576 }
03577 
03578 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
03579 
03580 #endif /* DBUS_BUILD_TESTS */