dbus-marshal-recursive-util.c

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

Generated on Fri Sep 21 18:12:12 2007 for D-Bus by  doxygen 1.5.1