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

Generated on Wed Jan 3 04:58:28 2007 for D-Bus by  doxygen 1.4.7