D-Bus  1.6.8
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 
01789     i = 0;
01790     while ((nodes[i] = value_generator (&i)))
01791       ;
01792 
01793     run_test_nodes (nodes, N_VALUES);
01794 
01795     for (i = 0; i < N_VALUES; i++)
01796       node_destroy (nodes[i]);
01797   }
01798 
01799   start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n",
01800                    N_VALUES * N_VALUES);
01801   {
01802     TestTypeNode *nodes[2];
01803 
01804     i = 0;
01805     while ((nodes[0] = value_generator (&i)))
01806       {
01807         j = 0;
01808         while ((nodes[1] = value_generator (&j)))
01809           {
01810             run_test_nodes (nodes, 2);
01811 
01812             node_destroy (nodes[1]);
01813           }
01814 
01815         node_destroy (nodes[0]);
01816       }
01817   }
01818 
01819   start_next_test ("Each container containing each value %d iterations\n",
01820                    N_CONTAINERS * N_VALUES);
01821   for (i = 0; i < N_CONTAINERS; i++)
01822     {
01823       const TestTypeNodeClass *container_klass = container_nodes[i];
01824 
01825       make_and_run_values_inside_container (container_klass, 1);
01826     }
01827 
01828   start_next_test ("Each container containing each value with arrays as blocks %d iterations\n",
01829                    N_CONTAINERS * N_VALUES);
01830   arrays_write_fixed_in_blocks = TRUE;
01831   for (i = 0; i < N_CONTAINERS; i++)
01832     {
01833       const TestTypeNodeClass *container_klass = container_nodes[i];
01834 
01835       make_and_run_values_inside_container (container_klass, 1);
01836     }
01837   arrays_write_fixed_in_blocks = FALSE;
01838 
01839   start_next_test ("Each container of same container of each value %d iterations\n",
01840                    N_CONTAINERS * N_VALUES);
01841   for (i = 0; i < N_CONTAINERS; i++)
01842     {
01843       const TestTypeNodeClass *container_klass = container_nodes[i];
01844 
01845       make_and_run_values_inside_container (container_klass, 2);
01846     }
01847 
01848   start_next_test ("Each container of same container of same container of each value %d iterations\n",
01849                    N_CONTAINERS * N_VALUES);
01850   for (i = 0; i < N_CONTAINERS; i++)
01851     {
01852       const TestTypeNodeClass *container_klass = container_nodes[i];
01853 
01854       make_and_run_values_inside_container (container_klass, 3);
01855     }
01856 
01857   start_next_test ("Each value,value pair inside a struct %d iterations\n",
01858                    N_VALUES * N_VALUES);
01859   {
01860     TestTypeNode *val1, *val2;
01861     TestTypeNode *node;
01862 
01863     node = node_new (&struct_1_class);
01864 
01865     i = 0;
01866     while ((val1 = value_generator (&i)))
01867       {
01868         j = 0;
01869         while ((val2 = value_generator (&j)))
01870           {
01871             TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01872 
01873             node_append_child (node, val1);
01874             node_append_child (node, val2);
01875 
01876             run_test_nodes (&node, 1);
01877 
01878             _dbus_list_clear (&container->children);
01879             node_destroy (val2);
01880           }
01881         node_destroy (val1);
01882       }
01883     node_destroy (node);
01884   }
01885 
01886   start_next_test ("All values in one big struct %d iteration\n",
01887                    1);
01888   {
01889     TestTypeNode *node;
01890     TestTypeNode *child;
01891 
01892     node = node_new (&struct_1_class);
01893 
01894     i = 0;
01895     while ((child = value_generator (&i)))
01896       node_append_child (node, child);
01897 
01898     run_test_nodes (&node, 1);
01899 
01900     node_destroy (node);
01901   }
01902 
01903   start_next_test ("Each value in a large array %d iterations\n",
01904                    N_VALUES);
01905   {
01906     TestTypeNode *val;
01907     TestTypeNode *node;
01908 
01909     node = node_new (&array_9_class);
01910 
01911     i = 0;
01912     while ((val = value_generator (&i)))
01913       {
01914         TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01915 
01916         node_append_child (node, val);
01917 
01918         run_test_nodes (&node, 1);
01919 
01920         _dbus_list_clear (&container->children);
01921         node_destroy (val);
01922       }
01923 
01924     node_destroy (node);
01925   }
01926 
01927   if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
01928       atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
01929     {
01930       fprintf (stderr, "skipping remaining marshal-recursive tests, "
01931           "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
01932       goto out;
01933     }
01934 
01935   start_next_test ("Each container of each container of each value %d iterations\n",
01936                    N_CONTAINERS * N_CONTAINERS * N_VALUES);
01937   for (i = 0; i < N_CONTAINERS; i++)
01938     {
01939       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
01940       TestTypeNode *outer_container = node_new (outer_container_klass);
01941 
01942       for (j = 0; j < N_CONTAINERS; j++)
01943         {
01944           TestTypeNode *child;
01945           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
01946           TestTypeNode *inner_container = node_new (inner_container_klass);
01947 
01948           node_append_child (outer_container, inner_container);
01949 
01950           m = 0;
01951           while ((child = value_generator (&m)))
01952             {
01953               node_append_child (inner_container, child);
01954 
01955               run_test_nodes (&outer_container, 1);
01956 
01957               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
01958               node_destroy (child);
01959             }
01960           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
01961           node_destroy (inner_container);
01962         }
01963       node_destroy (outer_container);
01964     }
01965 
01966   start_next_test ("Each container of each container of each container of each value %d iterations\n",
01967                    N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
01968   for (i = 0; i < N_CONTAINERS; i++)
01969     {
01970       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
01971       TestTypeNode *outer_container = node_new (outer_container_klass);
01972 
01973       for (j = 0; j < N_CONTAINERS; j++)
01974         {
01975           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
01976           TestTypeNode *inner_container = node_new (inner_container_klass);
01977 
01978           node_append_child (outer_container, inner_container);
01979 
01980           for (k = 0; k < N_CONTAINERS; k++)
01981             {
01982               TestTypeNode *child;
01983               const TestTypeNodeClass *center_container_klass = container_nodes[k];
01984               TestTypeNode *center_container = node_new (center_container_klass);
01985 
01986               node_append_child (inner_container, center_container);
01987 
01988               m = 0;
01989               while ((child = value_generator (&m)))
01990                 {
01991                   node_append_child (center_container, child);
01992 
01993                   run_test_nodes (&outer_container, 1);
01994 
01995                   _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
01996                   node_destroy (child);
01997                 }
01998               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
01999               node_destroy (center_container);
02000             }
02001           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
02002           node_destroy (inner_container);
02003         }
02004       node_destroy (outer_container);
02005     }
02006 
02007   /* This one takes a really long time (10 minutes on a Core2), so only enable
02008    * it if you're really sure */
02009   if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
02010     {
02011       fprintf (stderr, "skipping really slow marshal-recursive test, "
02012           "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
02013       goto out;
02014     }
02015 
02016   start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
02017                    N_VALUES * N_VALUES * N_VALUES);
02018   {
02019     TestTypeNode *nodes[3];
02020 
02021     i = 0;
02022     while ((nodes[0] = value_generator (&i)))
02023       {
02024         j = 0;
02025         while ((nodes[1] = value_generator (&j)))
02026           {
02027             k = 0;
02028             while ((nodes[2] = value_generator (&k)))
02029               {
02030                 run_test_nodes (nodes, 3);
02031 
02032                 node_destroy (nodes[2]);
02033               }
02034             node_destroy (nodes[1]);
02035           }
02036         node_destroy (nodes[0]);
02037       }
02038   }
02039 
02040 out:
02041   fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
02042            n_iterations_completed_total);
02043   fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
02044            MAX_INITIAL_OFFSET);
02045   fprintf (stderr, "out of memory handling %s tested\n",
02046            TEST_OOM_HANDLING ? "was" : "was not");
02047 }
02048 
02049 dbus_bool_t
02050 _dbus_marshal_recursive_test (void)
02051 {
02052   make_and_run_test_nodes ();
02053 
02054   return TRUE;
02055 }
02056 
02057 /*
02058  *
02059  *
02060  *         Implementations of each type node class
02061  *
02062  *
02063  *
02064  */
02065 #define MAX_MULTI_COUNT 5
02066 
02067 #define SAMPLE_INT16           1234
02068 #define SAMPLE_INT16_ALTERNATE 6785
02069 static dbus_int16_t
02070 int16_from_seed (int seed)
02071 {
02072   /* Generate an integer value that's predictable from seed.  We could
02073    * just use seed itself, but that would only ever touch one byte of
02074    * the int so would miss some kinds of bug.
02075    */
02076   dbus_int16_t v;
02077 
02078   v = 42; /* just to quiet compiler afaik */
02079   switch (seed % 5)
02080     {
02081     case 0:
02082       v = SAMPLE_INT16;
02083       break;
02084     case 1:
02085       v = SAMPLE_INT16_ALTERNATE;
02086       break;
02087     case 2:
02088       v = -1;
02089       break;
02090     case 3:
02091       v = _DBUS_INT16_MAX;
02092       break;
02093     case 4:
02094       v = 1;
02095       break;
02096     }
02097 
02098   if (seed > 1)
02099     v *= seed; /* wraps around eventually, which is fine */
02100 
02101   return v;
02102 }
02103 
02104 static dbus_bool_t
02105 int16_write_value (TestTypeNode   *node,
02106                    DataBlock      *block,
02107                    DBusTypeWriter *writer,
02108                    int             seed)
02109 {
02110   /* also used for uint16 */
02111   dbus_int16_t v;
02112 
02113   v = int16_from_seed (seed);
02114 
02115   return _dbus_type_writer_write_basic (writer,
02116                                         node->klass->typecode,
02117                                         &v);
02118 }
02119 
02120 static dbus_bool_t
02121 int16_read_value (TestTypeNode   *node,
02122                   DBusTypeReader *reader,
02123                   int             seed)
02124 {
02125   /* also used for uint16 */
02126   dbus_int16_t v;
02127 
02128   check_expected_type (reader, node->klass->typecode);
02129 
02130   _dbus_type_reader_read_basic (reader,
02131                                 (dbus_int16_t*) &v);
02132 
02133   _dbus_assert (v == int16_from_seed (seed));
02134 
02135   return TRUE;
02136 }
02137 
02138 static dbus_bool_t
02139 int16_set_value (TestTypeNode   *node,
02140                  DBusTypeReader *reader,
02141                  DBusTypeReader *realign_root,
02142                  int             seed)
02143 {
02144   /* also used for uint16 */
02145   dbus_int16_t v;
02146 
02147   v = int16_from_seed (seed);
02148 
02149   return _dbus_type_reader_set_basic (reader,
02150                                       &v,
02151                                       realign_root);
02152 }
02153 
02154 static dbus_bool_t
02155 int16_write_multi (TestTypeNode   *node,
02156                    DataBlock      *block,
02157                    DBusTypeWriter *writer,
02158                    int             seed,
02159                    int             count)
02160 {
02161   /* also used for uint16 */
02162   dbus_int16_t values[MAX_MULTI_COUNT];
02163   dbus_int16_t *v_ARRAY_INT16 = values;
02164   int i;
02165 
02166   for (i = 0; i < count; ++i)
02167     values[i] = int16_from_seed (seed + i);
02168 
02169   return _dbus_type_writer_write_fixed_multi (writer,
02170                                               node->klass->typecode,
02171                                               &v_ARRAY_INT16, count);
02172 }
02173 
02174 static dbus_bool_t
02175 int16_read_multi (TestTypeNode   *node,
02176                   DBusTypeReader *reader,
02177                   int             seed,
02178                   int             count)
02179 {
02180   /* also used for uint16 */
02181   dbus_int16_t *values;
02182   int n_elements;
02183   int i;
02184 
02185   check_expected_type (reader, node->klass->typecode);
02186 
02187   _dbus_type_reader_read_fixed_multi (reader,
02188                                       &values,
02189                                       &n_elements);
02190 
02191   if (n_elements != count)
02192     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
02193   _dbus_assert (n_elements == count);
02194 
02195   for (i = 0; i < count; i++)
02196     _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
02197                                                       (const unsigned char*)values + (i * 2))) ==
02198                   int16_from_seed (seed + i));
02199 
02200   return TRUE;
02201 }
02202 
02203 
02204 #define SAMPLE_INT32           12345678
02205 #define SAMPLE_INT32_ALTERNATE 53781429
02206 static dbus_int32_t
02207 int32_from_seed (int seed)
02208 {
02209   /* Generate an integer value that's predictable from seed.  We could
02210    * just use seed itself, but that would only ever touch one byte of
02211    * the int so would miss some kinds of bug.
02212    */
02213   dbus_int32_t v;
02214 
02215   v = 42; /* just to quiet compiler afaik */
02216   switch (seed % 5)
02217     {
02218     case 0:
02219       v = SAMPLE_INT32;
02220       break;
02221     case 1:
02222       v = SAMPLE_INT32_ALTERNATE;
02223       break;
02224     case 2:
02225       v = -1;
02226       break;
02227     case 3:
02228       v = _DBUS_INT_MAX;
02229       break;
02230     case 4:
02231       v = 1;
02232       break;
02233     }
02234 
02235   if (seed > 1)
02236     v *= seed; /* wraps around eventually, which is fine */
02237 
02238   return v;
02239 }
02240 
02241 static dbus_bool_t
02242 int32_write_value (TestTypeNode   *node,
02243                    DataBlock      *block,
02244                    DBusTypeWriter *writer,
02245                    int             seed)
02246 {
02247   /* also used for uint32 */
02248   dbus_int32_t v;
02249 
02250   v = int32_from_seed (seed);
02251 
02252   return _dbus_type_writer_write_basic (writer,
02253                                         node->klass->typecode,
02254                                         &v);
02255 }
02256 
02257 static dbus_bool_t
02258 int32_read_value (TestTypeNode   *node,
02259                   DBusTypeReader *reader,
02260                   int             seed)
02261 {
02262   /* also used for uint32 */
02263   dbus_int32_t v;
02264 
02265   check_expected_type (reader, node->klass->typecode);
02266 
02267   _dbus_type_reader_read_basic (reader,
02268                                 (dbus_int32_t*) &v);
02269 
02270   _dbus_assert (v == int32_from_seed (seed));
02271 
02272   return TRUE;
02273 }
02274 
02275 static dbus_bool_t
02276 int32_set_value (TestTypeNode   *node,
02277                  DBusTypeReader *reader,
02278                  DBusTypeReader *realign_root,
02279                  int             seed)
02280 {
02281   /* also used for uint32 */
02282   dbus_int32_t v;
02283 
02284   v = int32_from_seed (seed);
02285 
02286   return _dbus_type_reader_set_basic (reader,
02287                                       &v,
02288                                       realign_root);
02289 }
02290 
02291 static dbus_bool_t
02292 int32_write_multi (TestTypeNode   *node,
02293                    DataBlock      *block,
02294                    DBusTypeWriter *writer,
02295                    int             seed,
02296                    int             count)
02297 {
02298   /* also used for uint32 */
02299   dbus_int32_t values[MAX_MULTI_COUNT];
02300   dbus_int32_t *v_ARRAY_INT32 = values;
02301   int i;
02302 
02303   for (i = 0; i < count; ++i)
02304     values[i] = int32_from_seed (seed + i);
02305 
02306   return _dbus_type_writer_write_fixed_multi (writer,
02307                                               node->klass->typecode,
02308                                               &v_ARRAY_INT32, count);
02309 }
02310 
02311 static dbus_bool_t
02312 int32_read_multi (TestTypeNode   *node,
02313                   DBusTypeReader *reader,
02314                   int             seed,
02315                   int             count)
02316 {
02317   /* also used for uint32 */
02318   dbus_int32_t *values;
02319   int n_elements;
02320   int i;
02321 
02322   check_expected_type (reader, node->klass->typecode);
02323 
02324   _dbus_type_reader_read_fixed_multi (reader,
02325                                       &values,
02326                                       &n_elements);
02327 
02328   if (n_elements != count)
02329     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
02330   _dbus_assert (n_elements == count);
02331 
02332   for (i = 0; i < count; i++)
02333     _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order,
02334                                              (const unsigned char*)values + (i * 4))) ==
02335                   int32_from_seed (seed + i));
02336 
02337   return TRUE;
02338 }
02339 
02340 #ifdef DBUS_HAVE_INT64
02341 static dbus_int64_t
02342 int64_from_seed (int seed)
02343 {
02344   dbus_int32_t v32;
02345   dbus_int64_t v;
02346 
02347   v32 = int32_from_seed (seed);
02348 
02349   v = - (dbus_int32_t) ~ v32;
02350   v |= (((dbus_int64_t)v32) << 32);
02351 
02352   return v;
02353 }
02354 #endif
02355 
02356 static dbus_bool_t
02357 int64_write_value (TestTypeNode   *node,
02358                    DataBlock      *block,
02359                    DBusTypeWriter *writer,
02360                    int             seed)
02361 {
02362 #ifdef DBUS_HAVE_INT64
02363   /* also used for uint64 */
02364   dbus_int64_t v;
02365 
02366   v = int64_from_seed (seed);
02367 
02368   return _dbus_type_writer_write_basic (writer,
02369                                         node->klass->typecode,
02370                                         &v);
02371 #else
02372   return TRUE;
02373 #endif
02374 }
02375 
02376 static dbus_bool_t
02377 int64_read_value (TestTypeNode   *node,
02378                   DBusTypeReader *reader,
02379                   int             seed)
02380 {
02381 #ifdef DBUS_HAVE_INT64
02382   /* also used for uint64 */
02383   dbus_int64_t v;
02384 
02385   check_expected_type (reader, node->klass->typecode);
02386 
02387   _dbus_type_reader_read_basic (reader,
02388                                 (dbus_int64_t*) &v);
02389 
02390   _dbus_assert (v == int64_from_seed (seed));
02391 
02392   return TRUE;
02393 #else
02394   return TRUE;
02395 #endif
02396 }
02397 
02398 static dbus_bool_t
02399 int64_set_value (TestTypeNode   *node,
02400                  DBusTypeReader *reader,
02401                  DBusTypeReader *realign_root,
02402                  int             seed)
02403 {
02404 #ifdef DBUS_HAVE_INT64
02405   /* also used for uint64 */
02406   dbus_int64_t v;
02407 
02408   v = int64_from_seed (seed);
02409 
02410   return _dbus_type_reader_set_basic (reader,
02411                                       &v,
02412                                       realign_root);
02413 #else
02414   return TRUE;
02415 #endif
02416 }
02417 
02418 #define MAX_SAMPLE_STRING_LEN 10
02419 static void
02420 string_from_seed (char *buf,
02421                   int   len,
02422                   int   seed)
02423 {
02424   int i;
02425   unsigned char v;
02426 
02427   _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
02428 
02429   /* vary the length slightly, though we also have multiple string
02430    * value types for this, varying it here tests the set_value code
02431    */
02432   switch (seed % 3)
02433     {
02434     case 1:
02435       len += 2;
02436       break;
02437     case 2:
02438       len -= 2;
02439       break;
02440     }
02441   if (len < 0)
02442     len = 0;
02443 
02444   v = (unsigned char) ('A' + seed);
02445 
02446   i = 0;
02447   while (i < len)
02448     {
02449       if (v < 'A' || v > 'z')
02450         v = 'A';
02451 
02452       buf[i] = v;
02453 
02454       v += 1;
02455       ++i;
02456     }
02457 
02458   buf[i] = '\0';
02459 }
02460 
02461 static dbus_bool_t
02462 string_write_value (TestTypeNode   *node,
02463                     DataBlock      *block,
02464                     DBusTypeWriter *writer,
02465                     int             seed)
02466 {
02467   char buf[MAX_SAMPLE_STRING_LEN + 1]="";
02468   const char *v_string = buf;
02469 
02470 
02471   string_from_seed (buf, node->klass->subclass_detail,
02472                     seed);
02473 
02474   return _dbus_type_writer_write_basic (writer,
02475                                         node->klass->typecode,
02476                                         &v_string);
02477 }
02478 
02479 static dbus_bool_t
02480 string_read_value (TestTypeNode   *node,
02481                    DBusTypeReader *reader,
02482                    int             seed)
02483 {
02484   const char *v;
02485   char buf[MAX_SAMPLE_STRING_LEN + 1];
02486   v = buf;
02487 
02488   check_expected_type (reader, node->klass->typecode);
02489 
02490   _dbus_type_reader_read_basic (reader,
02491                                 (const char **) &v);
02492 
02493   string_from_seed (buf, node->klass->subclass_detail,
02494                     seed);
02495 
02496   if (strcmp (buf, v) != 0)
02497     {
02498       _dbus_warn ("read string '%s' expected '%s'\n",
02499                   v, buf);
02500       _dbus_assert_not_reached ("test failed");
02501     }
02502 
02503   return TRUE;
02504 }
02505 
02506 static dbus_bool_t
02507 string_set_value (TestTypeNode   *node,
02508                   DBusTypeReader *reader,
02509                   DBusTypeReader *realign_root,
02510                   int             seed)
02511 {
02512   char buf[MAX_SAMPLE_STRING_LEN + 1];
02513   const char *v_string = buf;
02514 
02515   string_from_seed (buf, node->klass->subclass_detail,
02516                     seed);
02517 
02518 #if RECURSIVE_MARSHAL_WRITE_TRACE
02519  {
02520    const char *old;
02521    _dbus_type_reader_read_basic (reader, &old);
02522    _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
02523                   v_string, strlen (v_string), old, strlen (old));
02524  }
02525 #endif
02526 
02527   return _dbus_type_reader_set_basic (reader,
02528                                       &v_string,
02529                                       realign_root);
02530 }
02531 
02532 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
02533 
02534 static dbus_bool_t
02535 bool_write_value (TestTypeNode   *node,
02536                   DataBlock      *block,
02537                   DBusTypeWriter *writer,
02538                   int             seed)
02539 {
02540   dbus_bool_t v;
02541 
02542   v = BOOL_FROM_SEED (seed);
02543 
02544   return _dbus_type_writer_write_basic (writer,
02545                                         node->klass->typecode,
02546                                         &v);
02547 }
02548 
02549 static dbus_bool_t
02550 bool_read_value (TestTypeNode   *node,
02551                  DBusTypeReader *reader,
02552                  int             seed)
02553 {
02554   dbus_bool_t v;
02555 
02556   check_expected_type (reader, node->klass->typecode);
02557 
02558   _dbus_type_reader_read_basic (reader,
02559                                 (unsigned char*) &v);
02560 
02561   _dbus_assert (v == BOOL_FROM_SEED (seed));
02562 
02563   return TRUE;
02564 }
02565 
02566 static dbus_bool_t
02567 bool_set_value (TestTypeNode   *node,
02568                 DBusTypeReader *reader,
02569                 DBusTypeReader *realign_root,
02570                 int             seed)
02571 {
02572   dbus_bool_t v;
02573 
02574   v = BOOL_FROM_SEED (seed);
02575 
02576   return _dbus_type_reader_set_basic (reader,
02577                                       &v,
02578                                       realign_root);
02579 }
02580 
02581 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
02582 
02583 static dbus_bool_t
02584 byte_write_value (TestTypeNode   *node,
02585                   DataBlock      *block,
02586                   DBusTypeWriter *writer,
02587                   int             seed)
02588 {
02589   unsigned char v;
02590 
02591   v = BYTE_FROM_SEED (seed);
02592 
02593   return _dbus_type_writer_write_basic (writer,
02594                                         node->klass->typecode,
02595                                         &v);
02596 }
02597 
02598 static dbus_bool_t
02599 byte_read_value (TestTypeNode   *node,
02600                  DBusTypeReader *reader,
02601                  int             seed)
02602 {
02603   unsigned char v;
02604 
02605   check_expected_type (reader, node->klass->typecode);
02606 
02607   _dbus_type_reader_read_basic (reader,
02608                                 (unsigned char*) &v);
02609 
02610   _dbus_assert (v == BYTE_FROM_SEED (seed));
02611 
02612   return TRUE;
02613 }
02614 
02615 
02616 static dbus_bool_t
02617 byte_set_value (TestTypeNode   *node,
02618                 DBusTypeReader *reader,
02619                 DBusTypeReader *realign_root,
02620                 int             seed)
02621 {
02622   unsigned char v;
02623 
02624   v = BYTE_FROM_SEED (seed);
02625 
02626   return _dbus_type_reader_set_basic (reader,
02627                                       &v,
02628                                       realign_root);
02629 }
02630 
02631 static double
02632 double_from_seed (int seed)
02633 {
02634   return SAMPLE_INT32 * (double) seed + 0.3;
02635 }
02636 
02637 static dbus_bool_t
02638 double_write_value (TestTypeNode   *node,
02639                     DataBlock      *block,
02640                     DBusTypeWriter *writer,
02641                     int             seed)
02642 {
02643   double v;
02644 
02645   v = double_from_seed (seed);
02646 
02647   return _dbus_type_writer_write_basic (writer,
02648                                         node->klass->typecode,
02649                                         &v);
02650 }
02651 
02652 static dbus_bool_t
02653 double_read_value (TestTypeNode   *node,
02654                    DBusTypeReader *reader,
02655                    int             seed)
02656 {
02657   double v;
02658   double expected;
02659 
02660   check_expected_type (reader, node->klass->typecode);
02661 
02662   _dbus_type_reader_read_basic (reader,
02663                                 (double*) &v);
02664 
02665   expected = double_from_seed (seed);
02666 
02667   if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
02668     {
02669 #ifdef DBUS_INT64_PRINTF_MODIFIER
02670       _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",
02671                   expected, v,
02672                   *(dbus_uint64_t*)(char*)&expected,
02673                   *(dbus_uint64_t*)(char*)&v);
02674 #endif
02675       _dbus_assert_not_reached ("test failed");
02676     }
02677 
02678   return TRUE;
02679 }
02680 
02681 static dbus_bool_t
02682 double_set_value (TestTypeNode   *node,
02683                 DBusTypeReader *reader,
02684                 DBusTypeReader *realign_root,
02685                 int             seed)
02686 {
02687   double v;
02688 
02689   v = double_from_seed (seed);
02690 
02691   return _dbus_type_reader_set_basic (reader,
02692                                       &v,
02693                                       realign_root);
02694 }
02695 
02696 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
02697 static void
02698 object_path_from_seed (char *buf,
02699                        int   seed)
02700 {
02701   int i;
02702   unsigned char v;
02703   int len;
02704 
02705   len = seed % 9;
02706   _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
02707 
02708   v = (unsigned char) ('A' + seed);
02709 
02710   if (len < 2)
02711     {
02712       buf[0] = '/';
02713       i = 1;
02714     }
02715   else
02716     {
02717       i = 0;
02718       while (i + 1 < len)
02719         {
02720           if (v < 'A' || v > 'z')
02721             v = 'A';
02722 
02723           buf[i] = '/';
02724           ++i;
02725           buf[i] = v;
02726           ++i;
02727           
02728           v += 1;
02729         }
02730     }
02731 
02732   buf[i] = '\0';
02733 }
02734 
02735 static dbus_bool_t
02736 object_path_write_value (TestTypeNode   *node,
02737                          DataBlock      *block,
02738                          DBusTypeWriter *writer,
02739                          int             seed)
02740 {
02741   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02742   const char *v_string = buf;
02743 
02744   object_path_from_seed (buf, seed);
02745 
02746   return _dbus_type_writer_write_basic (writer,
02747                                         node->klass->typecode,
02748                                         &v_string);
02749 }
02750 
02751 static dbus_bool_t
02752 object_path_read_value (TestTypeNode   *node,
02753                         DBusTypeReader *reader,
02754                         int             seed)
02755 {
02756   const char *v;
02757   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02758 
02759   check_expected_type (reader, node->klass->typecode);
02760 
02761   _dbus_type_reader_read_basic (reader,
02762                                 (const char **) &v);
02763 
02764   object_path_from_seed (buf, seed);
02765 
02766   if (strcmp (buf, v) != 0)
02767     {
02768       _dbus_warn ("read object path '%s' expected '%s'\n",
02769                   v, buf);
02770       _dbus_assert_not_reached ("test failed");
02771     }
02772 
02773   return TRUE;
02774 }
02775 
02776 static dbus_bool_t
02777 object_path_set_value (TestTypeNode   *node,
02778                        DBusTypeReader *reader,
02779                        DBusTypeReader *realign_root,
02780                        int             seed)
02781 {
02782   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02783   const char *v_string = buf;
02784 
02785   object_path_from_seed (buf, seed);
02786 
02787   return _dbus_type_reader_set_basic (reader,
02788                                       &v_string,
02789                                       realign_root);
02790 }
02791 
02792 #define MAX_SAMPLE_SIGNATURE_LEN 10
02793 static void
02794 signature_from_seed (char *buf,
02795                      int   seed)
02796 {
02797   /* try to avoid ascending, descending, or alternating length to help find bugs */
02798   const char *sample_signatures[] = {
02799     "asax"
02800     "",
02801     "asau(xxxx)",
02802     "x",
02803     "ai",
02804     "a(ii)"
02805   };
02806 
02807   strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
02808 }
02809 
02810 static dbus_bool_t
02811 signature_write_value (TestTypeNode   *node,
02812                        DataBlock      *block,
02813                        DBusTypeWriter *writer,
02814                        int             seed)
02815 {
02816   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02817   const char *v_string = buf;
02818 
02819   signature_from_seed (buf, seed);
02820 
02821   return _dbus_type_writer_write_basic (writer,
02822                                         node->klass->typecode,
02823                                         &v_string);
02824 }
02825 
02826 static dbus_bool_t
02827 signature_read_value (TestTypeNode   *node,
02828                       DBusTypeReader *reader,
02829                       int             seed)
02830 {
02831   const char *v;
02832   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02833 
02834   check_expected_type (reader, node->klass->typecode);
02835 
02836   _dbus_type_reader_read_basic (reader,
02837                                 (const char **) &v);
02838 
02839   signature_from_seed (buf, seed);
02840 
02841   if (strcmp (buf, v) != 0)
02842     {
02843       _dbus_warn ("read signature value '%s' expected '%s'\n",
02844                   v, buf);
02845       _dbus_assert_not_reached ("test failed");
02846     }
02847 
02848   return TRUE;
02849 }
02850 
02851 
02852 static dbus_bool_t
02853 signature_set_value (TestTypeNode   *node,
02854                      DBusTypeReader *reader,
02855                      DBusTypeReader *realign_root,
02856                      int             seed)
02857 {
02858   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02859   const char *v_string = buf;
02860 
02861   signature_from_seed (buf, seed);
02862 
02863   return _dbus_type_reader_set_basic (reader,
02864                                       &v_string,
02865                                       realign_root);
02866 }
02867 
02868 static dbus_bool_t
02869 struct_write_value (TestTypeNode   *node,
02870                     DataBlock      *block,
02871                     DBusTypeWriter *writer,
02872                     int             seed)
02873 {
02874   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02875   DataBlockState saved;
02876   DBusTypeWriter sub;
02877   int i;
02878   int n_copies;
02879 
02880   n_copies = node->klass->subclass_detail;
02881 
02882   _dbus_assert (container->children != NULL);
02883 
02884   data_block_save (block, &saved);
02885 
02886   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
02887                                   NULL, 0,
02888                                   &sub))
02889     return FALSE;
02890 
02891   i = 0;
02892   while (i < n_copies)
02893     {
02894       DBusList *link;
02895 
02896       link = _dbus_list_get_first_link (&container->children);
02897       while (link != NULL)
02898         {
02899           TestTypeNode *child = link->data;
02900           DBusList *next = _dbus_list_get_next_link (&container->children, link);
02901 
02902           if (!node_write_value (child, block, &sub, seed + i))
02903             {
02904               data_block_restore (block, &saved);
02905               return FALSE;
02906             }
02907 
02908           link = next;
02909         }
02910 
02911       ++i;
02912     }
02913 
02914   if (!_dbus_type_writer_unrecurse (writer, &sub))
02915     {
02916       data_block_restore (block, &saved);
02917       return FALSE;
02918     }
02919 
02920   return TRUE;
02921 }
02922 
02923 static dbus_bool_t
02924 struct_read_or_set_value (TestTypeNode   *node,
02925                           DBusTypeReader *reader,
02926                           DBusTypeReader *realign_root,
02927                           int             seed)
02928 {
02929   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02930   DBusTypeReader sub;
02931   int i;
02932   int n_copies;
02933 
02934   n_copies = node->klass->subclass_detail;
02935 
02936   check_expected_type (reader, DBUS_TYPE_STRUCT);
02937 
02938   _dbus_type_reader_recurse (reader, &sub);
02939 
02940   i = 0;
02941   while (i < n_copies)
02942     {
02943       DBusList *link;
02944 
02945       link = _dbus_list_get_first_link (&container->children);
02946       while (link != NULL)
02947         {
02948           TestTypeNode *child = link->data;
02949           DBusList *next = _dbus_list_get_next_link (&container->children, link);
02950 
02951           if (realign_root == NULL)
02952             {
02953               if (!node_read_value (child, &sub, seed + i))
02954                 return FALSE;
02955             }
02956           else
02957             {
02958               if (!node_set_value (child, &sub, realign_root, seed + i))
02959                 return FALSE;
02960             }
02961 
02962           if (i == (n_copies - 1) && next == NULL)
02963             NEXT_EXPECTING_FALSE (&sub);
02964           else
02965             NEXT_EXPECTING_TRUE (&sub);
02966 
02967           link = next;
02968         }
02969 
02970       ++i;
02971     }
02972 
02973   return TRUE;
02974 }
02975 
02976 static dbus_bool_t
02977 struct_read_value (TestTypeNode   *node,
02978                    DBusTypeReader *reader,
02979                    int             seed)
02980 {
02981   return struct_read_or_set_value (node, reader, NULL, seed);
02982 }
02983 
02984 static dbus_bool_t
02985 struct_set_value (TestTypeNode   *node,
02986                   DBusTypeReader *reader,
02987                   DBusTypeReader *realign_root,
02988                   int             seed)
02989 {
02990   return struct_read_or_set_value (node, reader, realign_root, seed);
02991 }
02992 
02993 static dbus_bool_t
02994 struct_build_signature (TestTypeNode   *node,
02995                         DBusString     *str)
02996 {
02997   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02998   int i;
02999   int orig_len;
03000   int n_copies;
03001 
03002   n_copies = node->klass->subclass_detail;
03003 
03004   orig_len = _dbus_string_get_length (str);
03005 
03006   if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
03007     goto oom;
03008 
03009   i = 0;
03010   while (i < n_copies)
03011     {
03012       DBusList *link;
03013 
03014       link = _dbus_list_get_first_link (&container->children);
03015       while (link != NULL)
03016         {
03017           TestTypeNode *child = link->data;
03018           DBusList *next = _dbus_list_get_next_link (&container->children, link);
03019 
03020           if (!node_build_signature (child, str))
03021             goto oom;
03022 
03023           link = next;
03024         }
03025 
03026       ++i;
03027     }
03028 
03029   if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
03030     goto oom;
03031 
03032   return TRUE;
03033 
03034  oom:
03035   _dbus_string_set_length (str, orig_len);
03036   return FALSE;
03037 }
03038 
03039 static dbus_bool_t
03040 array_write_value (TestTypeNode   *node,
03041                    DataBlock      *block,
03042                    DBusTypeWriter *writer,
03043                    int             seed)
03044 {
03045   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03046   DataBlockState saved;
03047   DBusTypeWriter sub;
03048   DBusString element_signature;
03049   int i;
03050   int n_copies;
03051   int element_type;
03052   TestTypeNode *child;
03053 
03054   n_copies = node->klass->subclass_detail;
03055 
03056   _dbus_assert (container->children != NULL);
03057 
03058   data_block_save (block, &saved);
03059 
03060   if (!_dbus_string_init (&element_signature))
03061     return FALSE;
03062 
03063   child = _dbus_list_get_first (&container->children);
03064 
03065   if (!node_build_signature (child,
03066                              &element_signature))
03067     goto oom;
03068 
03069   element_type = _dbus_first_type_in_signature (&element_signature, 0);
03070 
03071   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
03072                                   &element_signature, 0,
03073                                   &sub))
03074     goto oom;
03075 
03076   if (arrays_write_fixed_in_blocks &&
03077       dbus_type_is_fixed (element_type) &&
03078       child->klass->write_multi)
03079     {
03080       if (!node_write_multi (child, block, &sub, seed, n_copies))
03081         goto oom;
03082     }
03083   else
03084     {
03085       i = 0;
03086       while (i < n_copies)
03087         {
03088           DBusList *link;
03089 
03090           link = _dbus_list_get_first_link (&container->children);
03091           while (link != NULL)
03092             {
03093               TestTypeNode *child = link->data;
03094               DBusList *next = _dbus_list_get_next_link (&container->children, link);
03095 
03096               if (!node_write_value (child, block, &sub, seed + i))
03097                 goto oom;
03098 
03099               link = next;
03100             }
03101 
03102           ++i;
03103         }
03104     }
03105 
03106   if (!_dbus_type_writer_unrecurse (writer, &sub))
03107     goto oom;
03108 
03109   _dbus_string_free (&element_signature);
03110   return TRUE;
03111 
03112  oom:
03113   data_block_restore (block, &saved);
03114   _dbus_string_free (&element_signature);
03115   return FALSE;
03116 }
03117 
03118 static dbus_bool_t
03119 array_read_or_set_value (TestTypeNode   *node,
03120                          DBusTypeReader *reader,
03121                          DBusTypeReader *realign_root,
03122                          int             seed)
03123 {
03124   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03125   DBusTypeReader sub;
03126   int i;
03127   int n_copies;
03128   TestTypeNode *child;
03129 
03130   n_copies = node->klass->subclass_detail;
03131 
03132   check_expected_type (reader, DBUS_TYPE_ARRAY);
03133 
03134   child = _dbus_list_get_first (&container->children);
03135 
03136   if (n_copies > 0)
03137     {
03138       _dbus_type_reader_recurse (reader, &sub);
03139 
03140       if (realign_root == NULL && arrays_write_fixed_in_blocks &&
03141           dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
03142           child->klass->read_multi)
03143         {
03144           if (!node_read_multi (child, &sub, seed, n_copies))
03145             return FALSE;
03146         }
03147       else
03148         {
03149           i = 0;
03150           while (i < n_copies)
03151             {
03152               DBusList *link;
03153 
03154               link = _dbus_list_get_first_link (&container->children);
03155               while (link != NULL)
03156                 {
03157                   TestTypeNode *child = link->data;
03158                   DBusList *next = _dbus_list_get_next_link (&container->children, link);
03159 
03160                   _dbus_assert (child->klass->typecode ==
03161                                 _dbus_type_reader_get_element_type (reader));
03162 
03163                   if (realign_root == NULL)
03164                     {
03165                       if (!node_read_value (child, &sub, seed + i))
03166                         return FALSE;
03167                     }
03168                   else
03169                     {
03170                       if (!node_set_value (child, &sub, realign_root, seed + i))
03171                         return FALSE;
03172                     }
03173 
03174                   if (i == (n_copies - 1) && next == NULL)
03175                     NEXT_EXPECTING_FALSE (&sub);
03176                   else
03177                     NEXT_EXPECTING_TRUE (&sub);
03178 
03179                   link = next;
03180                 }
03181 
03182               ++i;
03183             }
03184         }
03185     }
03186 
03187   return TRUE;
03188 }
03189 
03190 static dbus_bool_t
03191 array_read_value (TestTypeNode   *node,
03192                   DBusTypeReader *reader,
03193                   int             seed)
03194 {
03195   return array_read_or_set_value (node, reader, NULL, seed);
03196 }
03197 
03198 static dbus_bool_t
03199 array_set_value (TestTypeNode   *node,
03200                  DBusTypeReader *reader,
03201                  DBusTypeReader *realign_root,
03202                  int             seed)
03203 {
03204   return array_read_or_set_value (node, reader, realign_root, seed);
03205 }
03206 
03207 static dbus_bool_t
03208 array_build_signature (TestTypeNode   *node,
03209                        DBusString     *str)
03210 {
03211   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03212   int orig_len;
03213 
03214   orig_len = _dbus_string_get_length (str);
03215 
03216   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
03217     goto oom;
03218 
03219   if (!node_build_signature (_dbus_list_get_first (&container->children),
03220                              str))
03221     goto oom;
03222 
03223   return TRUE;
03224 
03225  oom:
03226   _dbus_string_set_length (str, orig_len);
03227   return FALSE;
03228 }
03229 
03230  /* 10 is random just to add another seed that we use in the suite */
03231 #define VARIANT_SEED 10
03232 
03233 static dbus_bool_t
03234 variant_write_value (TestTypeNode   *node,
03235                      DataBlock      *block,
03236                      DBusTypeWriter *writer,
03237                      int             seed)
03238 {
03239   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03240   DataBlockState saved;
03241   DBusTypeWriter sub;
03242   DBusString content_signature;
03243   TestTypeNode *child;
03244 
03245   _dbus_assert (container->children != NULL);
03246   _dbus_assert (_dbus_list_length_is_one (&container->children));
03247 
03248   child = _dbus_list_get_first (&container->children);
03249 
03250   data_block_save (block, &saved);
03251 
03252   if (!_dbus_string_init (&content_signature))
03253     return FALSE;
03254 
03255   if (!node_build_signature (child,
03256                              &content_signature))
03257     goto oom;
03258 
03259   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
03260                                   &content_signature, 0,
03261                                   &sub))
03262     goto oom;
03263 
03264   if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
03265     goto oom;
03266 
03267   if (!_dbus_type_writer_unrecurse (writer, &sub))
03268     goto oom;
03269 
03270   _dbus_string_free (&content_signature);
03271   return TRUE;
03272 
03273  oom:
03274   data_block_restore (block, &saved);
03275   _dbus_string_free (&content_signature);
03276   return FALSE;
03277 }
03278 
03279 static dbus_bool_t
03280 variant_read_or_set_value (TestTypeNode   *node,
03281                            DBusTypeReader *reader,
03282                            DBusTypeReader *realign_root,
03283                            int             seed)
03284 {
03285   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03286   DBusTypeReader sub;
03287   TestTypeNode *child;
03288 
03289   _dbus_assert (container->children != NULL);
03290   _dbus_assert (_dbus_list_length_is_one (&container->children));
03291 
03292   child = _dbus_list_get_first (&container->children);
03293 
03294   check_expected_type (reader, DBUS_TYPE_VARIANT);
03295 
03296   _dbus_type_reader_recurse (reader, &sub);
03297 
03298   if (realign_root == NULL)
03299     {
03300       if (!node_read_value (child, &sub, seed + VARIANT_SEED))
03301         return FALSE;
03302     }
03303   else
03304     {
03305       if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
03306         return FALSE;
03307     }
03308 
03309   NEXT_EXPECTING_FALSE (&sub);
03310 
03311   return TRUE;
03312 }
03313 
03314 static dbus_bool_t
03315 variant_read_value (TestTypeNode   *node,
03316                     DBusTypeReader *reader,
03317                     int             seed)
03318 {
03319   return variant_read_or_set_value (node, reader, NULL, seed);
03320 }
03321 
03322 static dbus_bool_t
03323 variant_set_value (TestTypeNode   *node,
03324                    DBusTypeReader *reader,
03325                    DBusTypeReader *realign_root,
03326                    int             seed)
03327 {
03328   return variant_read_or_set_value (node, reader, realign_root, seed);
03329 }
03330 
03331 static dbus_bool_t
03332 dict_write_value (TestTypeNode   *node,
03333                   DataBlock      *block,
03334                   DBusTypeWriter *writer,
03335                   int             seed)
03336 {
03337   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03338   DataBlockState saved;
03339   DBusTypeWriter sub;
03340   DBusString entry_value_signature;
03341   DBusString dict_entry_signature;
03342   int i;
03343   int n_entries;
03344   TestTypeNode *child;
03345 
03346   n_entries = node->klass->subclass_detail;
03347 
03348   _dbus_assert (container->children != NULL);
03349 
03350   data_block_save (block, &saved);
03351 
03352   if (!_dbus_string_init (&entry_value_signature))
03353     return FALSE;
03354 
03355   if (!_dbus_string_init (&dict_entry_signature))
03356     {
03357       _dbus_string_free (&entry_value_signature);
03358       return FALSE;
03359     }
03360   
03361   child = _dbus_list_get_first (&container->children);
03362 
03363   if (!node_build_signature (child,
03364                              &entry_value_signature))
03365     goto oom;
03366 
03367   if (!_dbus_string_append (&dict_entry_signature,
03368                             DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
03369                             DBUS_TYPE_INT32_AS_STRING))
03370     goto oom;
03371 
03372   if (!_dbus_string_copy (&entry_value_signature, 0,
03373                           &dict_entry_signature,
03374                           _dbus_string_get_length (&dict_entry_signature)))
03375     goto oom;
03376 
03377   if (!_dbus_string_append_byte (&dict_entry_signature,
03378                                  DBUS_DICT_ENTRY_END_CHAR))
03379     goto oom;
03380 
03381   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
03382                                   &dict_entry_signature, 0,
03383                                   &sub))
03384     goto oom;
03385 
03386   i = 0;
03387   while (i < n_entries)
03388     {
03389       DBusTypeWriter entry_sub;
03390       dbus_int32_t key;
03391 
03392       if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
03393                                       NULL, 0,
03394                                       &entry_sub))
03395         goto oom;
03396 
03397       key = int32_from_seed (seed + i);
03398 
03399       if (!_dbus_type_writer_write_basic (&entry_sub,
03400                                           DBUS_TYPE_INT32,
03401                                           &key))
03402         goto oom;
03403       
03404       if (!node_write_value (child, block, &entry_sub, seed + i))
03405         goto oom;
03406 
03407       if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
03408         goto oom;
03409       
03410       ++i;
03411     }
03412 
03413   if (!_dbus_type_writer_unrecurse (writer, &sub))
03414     goto oom;
03415   
03416   _dbus_string_free (&entry_value_signature);
03417   _dbus_string_free (&dict_entry_signature);
03418   return TRUE;
03419 
03420  oom:
03421   data_block_restore (block, &saved);
03422   _dbus_string_free (&entry_value_signature);
03423   _dbus_string_free (&dict_entry_signature);
03424   return FALSE;
03425 }
03426 
03427 static dbus_bool_t
03428 dict_read_or_set_value (TestTypeNode   *node,
03429                         DBusTypeReader *reader,
03430                         DBusTypeReader *realign_root,
03431                         int             seed)
03432 {
03433   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03434   DBusTypeReader sub;
03435   int i;
03436   int n_entries;
03437   TestTypeNode *child;
03438 
03439   n_entries = node->klass->subclass_detail;
03440 
03441   check_expected_type (reader, DBUS_TYPE_ARRAY);
03442 
03443   child = _dbus_list_get_first (&container->children);
03444 
03445   if (n_entries > 0)
03446     {
03447       _dbus_type_reader_recurse (reader, &sub);
03448 
03449       check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
03450       
03451       i = 0;
03452       while (i < n_entries)
03453         {
03454           DBusTypeReader entry_sub;
03455 
03456           check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
03457           
03458           _dbus_type_reader_recurse (&sub, &entry_sub);
03459           
03460           if (realign_root == NULL)
03461             {
03462               dbus_int32_t v;
03463               
03464               check_expected_type (&entry_sub, DBUS_TYPE_INT32);
03465 
03466               _dbus_type_reader_read_basic (&entry_sub,
03467                                             (dbus_int32_t*) &v);
03468 
03469               _dbus_assert (v == int32_from_seed (seed + i));
03470 
03471               NEXT_EXPECTING_TRUE (&entry_sub);
03472               
03473               if (!node_read_value (child, &entry_sub, seed + i))
03474                 return FALSE;
03475 
03476               NEXT_EXPECTING_FALSE (&entry_sub);
03477             }
03478           else
03479             {
03480               dbus_int32_t v;
03481               
03482               v = int32_from_seed (seed + i);
03483               
03484               if (!_dbus_type_reader_set_basic (&entry_sub,
03485                                                 &v,
03486                                                 realign_root))
03487                 return FALSE;
03488 
03489               NEXT_EXPECTING_TRUE (&entry_sub);
03490               
03491               if (!node_set_value (child, &entry_sub, realign_root, seed + i))
03492                 return FALSE;
03493 
03494               NEXT_EXPECTING_FALSE (&entry_sub);
03495             }
03496           
03497           if (i == (n_entries - 1))
03498             NEXT_EXPECTING_FALSE (&sub);
03499           else
03500             NEXT_EXPECTING_TRUE (&sub);
03501 
03502           ++i;
03503         }
03504     }
03505 
03506   return TRUE;
03507 }
03508 
03509 static dbus_bool_t
03510 dict_read_value (TestTypeNode   *node,
03511                  DBusTypeReader *reader,
03512                  int             seed)
03513 {
03514   return dict_read_or_set_value (node, reader, NULL, seed);
03515 }
03516 
03517 static dbus_bool_t
03518 dict_set_value (TestTypeNode   *node,
03519                 DBusTypeReader *reader,
03520                 DBusTypeReader *realign_root,
03521                 int             seed)
03522 {
03523   return dict_read_or_set_value (node, reader, realign_root, seed);
03524 }
03525 
03526 static dbus_bool_t
03527 dict_build_signature (TestTypeNode   *node,
03528                       DBusString     *str)
03529 {
03530   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03531   int orig_len;
03532 
03533   orig_len = _dbus_string_get_length (str);
03534 
03535   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
03536     goto oom;
03537 
03538   if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
03539     goto oom;
03540   
03541   if (!node_build_signature (_dbus_list_get_first (&container->children),
03542                              str))
03543     goto oom;
03544 
03545   if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
03546     goto oom;
03547 
03548   return TRUE;
03549 
03550  oom:
03551   _dbus_string_set_length (str, orig_len);
03552   return FALSE;
03553 }
03554 
03555 static void
03556 container_destroy (TestTypeNode *node)
03557 {
03558   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03559   DBusList *link;
03560 
03561   link = _dbus_list_get_first_link (&container->children);
03562   while (link != NULL)
03563     {
03564       TestTypeNode *child = link->data;
03565       DBusList *next = _dbus_list_get_next_link (&container->children, link);
03566 
03567       node_destroy (child);
03568 
03569       _dbus_list_free_link (link);
03570 
03571       link = next;
03572     }
03573 }
03574 
03575 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */
03576 
03577 #endif /* DBUS_BUILD_TESTS */