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