Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

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 FALSE;
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   DBusTypeMark mark;
00987   DBusTypeReader restored;
00988 
00989   _dbus_type_reader_save_mark (reader, &mark);
00990 
00991   if (!(* node->klass->read_value) (node, reader, seed))
00992     return FALSE;
00993 
00994   _dbus_type_reader_init_from_mark (&restored,
00995                                     reader->byte_order,
00996                                     reader->type_str,
00997                                     reader->value_str,
00998                                     &mark);
00999 
01000   if (!(* node->klass->read_value) (node, &restored, seed))
01001     return FALSE;
01002 
01003   return TRUE;
01004 }
01005 
01006 /* Warning: if this one fails due to OOM, it has side effects (can
01007  * modify only some of the sub-values). OK in a test suite, but we
01008  * never do this in real code.
01009  */
01010 static dbus_bool_t
01011 node_set_value (TestTypeNode   *node,
01012                 DBusTypeReader *reader,
01013                 DBusTypeReader *realign_root,
01014                 int             seed)
01015 {
01016   if (!(* node->klass->set_value) (node, reader, realign_root, seed))
01017     return FALSE;
01018 
01019   return TRUE;
01020 }
01021 
01022 static dbus_bool_t
01023 node_build_signature (TestTypeNode *node,
01024                       DBusString   *str)
01025 {
01026   if (node->klass->build_signature)
01027     return (* node->klass->build_signature) (node, str);
01028   else
01029     return _dbus_string_append_byte (str, node->klass->typecode);
01030 }
01031 
01032 static dbus_bool_t
01033 node_append_child (TestTypeNode *node,
01034                    TestTypeNode *child)
01035 {
01036   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01037 
01038   _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
01039 
01040   if (!_dbus_list_append (&container->children, child))
01041     _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 */
01042 
01043   return TRUE;
01044 }
01045 
01046 static dbus_bool_t
01047 node_write_multi (TestTypeNode   *node,
01048                   DataBlock      *block,
01049                   DBusTypeWriter *writer,
01050                   int             seed,
01051                   int             n_copies)
01052 {
01053   dbus_bool_t retval;
01054 
01055   _dbus_assert (node->klass->write_multi != NULL);
01056   retval = (* node->klass->write_multi) (node, block, writer, seed, n_copies);
01057 
01058 #if 0
01059   /* Handy to see where things break, but too expensive to do all the time */
01060   data_block_verify (block);
01061 #endif
01062 
01063   return retval;
01064 }
01065 
01066 static dbus_bool_t
01067 node_read_multi (TestTypeNode   *node,
01068                  DBusTypeReader *reader,
01069                  int             seed,
01070                  int             n_copies)
01071 {
01072   _dbus_assert (node->klass->read_multi != NULL);
01073 
01074   if (!(* node->klass->read_multi) (node, reader, seed, n_copies))
01075     return FALSE;
01076 
01077   return TRUE;
01078 }
01079 
01080 static int n_iterations_completed_total = 0;
01081 static int n_iterations_completed_this_test = 0;
01082 static int n_iterations_expected_this_test = 0;
01083 
01084 typedef struct
01085 {
01086   const DBusString   *signature;
01087   DataBlock          *block;
01088   int                 type_offset;
01089   TestTypeNode      **nodes;
01090   int                 n_nodes;
01091 } NodeIterationData;
01092 
01093 static dbus_bool_t
01094 run_test_copy (NodeIterationData *nid)
01095 {
01096   DataBlock *src;
01097   DataBlock dest;
01098   dbus_bool_t retval;
01099   DBusTypeReader reader;
01100   DBusTypeWriter writer;
01101 
01102   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
01103 
01104   src = nid->block;
01105 
01106   retval = FALSE;
01107 
01108   if (!data_block_init (&dest, src->byte_order, src->initial_offset))
01109     return FALSE;
01110 
01111   data_block_init_reader_writer (src, &reader, NULL);
01112   data_block_init_reader_writer (&dest, NULL, &writer);
01113 
01114   /* DBusTypeWriter assumes it's writing into an existing signature,
01115    * so doesn't add nul on its own. We have to do that.
01116    */
01117   if (!_dbus_string_insert_byte (&dest.signature,
01118                                  dest.initial_offset, '\0'))
01119     goto out;
01120 
01121   if (!_dbus_type_writer_write_reader (&writer, &reader))
01122     goto out;
01123 
01124   /* Data blocks should now be identical */
01125   if (!_dbus_string_equal (&src->signature, &dest.signature))
01126     {
01127       _dbus_verbose ("SOURCE\n");
01128       _dbus_verbose_bytes_of_string (&src->signature, 0,
01129                                      _dbus_string_get_length (&src->signature));
01130       _dbus_verbose ("DEST\n");
01131       _dbus_verbose_bytes_of_string (&dest.signature, 0,
01132                                      _dbus_string_get_length (&dest.signature));
01133       _dbus_assert_not_reached ("signatures did not match");
01134     }
01135 
01136   if (!_dbus_string_equal (&src->body, &dest.body))
01137     {
01138       _dbus_verbose ("SOURCE\n");
01139       _dbus_verbose_bytes_of_string (&src->body, 0,
01140                                      _dbus_string_get_length (&src->body));
01141       _dbus_verbose ("DEST\n");
01142       _dbus_verbose_bytes_of_string (&dest.body, 0,
01143                                      _dbus_string_get_length (&dest.body));
01144       _dbus_assert_not_reached ("bodies did not match");
01145     }
01146 
01147   retval = TRUE;
01148 
01149  out:
01150 
01151   data_block_free (&dest);
01152 
01153   return retval;
01154 }
01155 
01156 static dbus_bool_t
01157 run_test_values_only_write (NodeIterationData *nid)
01158 {
01159   DBusTypeReader reader;
01160   DBusTypeWriter writer;
01161   int i;
01162   dbus_bool_t retval;
01163   int sig_len;
01164 
01165   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
01166 
01167   retval = FALSE;
01168 
01169   data_block_reset (nid->block);
01170 
01171   sig_len = _dbus_string_get_length (nid->signature);
01172 
01173   _dbus_type_writer_init_values_only (&writer,
01174                                       nid->block->byte_order,
01175                                       nid->signature, 0,
01176                                       &nid->block->body,
01177                                       _dbus_string_get_length (&nid->block->body) - N_FENCE_BYTES);
01178   _dbus_type_reader_init (&reader,
01179                           nid->block->byte_order,
01180                           nid->signature, 0,
01181                           &nid->block->body,
01182                           nid->block->initial_offset);
01183 
01184   i = 0;
01185   while (i < nid->n_nodes)
01186     {
01187       if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
01188         goto out;
01189 
01190       ++i;
01191     }
01192 
01193   /* if we wrote any typecodes then this would fail */
01194   _dbus_assert (sig_len == _dbus_string_get_length (nid->signature));
01195 
01196   /* But be sure we wrote out the values correctly */
01197   i = 0;
01198   while (i < nid->n_nodes)
01199     {
01200       if (!node_read_value (nid->nodes[i], &reader, i))
01201         goto out;
01202 
01203       if (i + 1 == nid->n_nodes)
01204         NEXT_EXPECTING_FALSE (&reader);
01205       else
01206         NEXT_EXPECTING_TRUE (&reader);
01207 
01208       ++i;
01209     }
01210 
01211   retval = TRUE;
01212 
01213  out:
01214   data_block_reset (nid->block);
01215   return retval;
01216 }
01217 
01218 /* offset the seed for setting, so we set different numbers than
01219  * we originally wrote. Don't offset by a huge number since in
01220  * some cases it's value = possibilities[seed % n_possibilities]
01221  * and we don't want to wrap around. bool_from_seed
01222  * is just seed % 2 even.
01223  */
01224 #define SET_SEED 1
01225 static dbus_bool_t
01226 run_test_set_values (NodeIterationData *nid)
01227 {
01228   DBusTypeReader reader;
01229   DBusTypeReader realign_root;
01230   dbus_bool_t retval;
01231   int i;
01232 
01233   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
01234 
01235   retval = FALSE;
01236 
01237   data_block_init_reader_writer (nid->block,
01238                                  &reader, NULL);
01239 
01240   realign_root = reader;
01241 
01242   i = 0;
01243   while (i < nid->n_nodes)
01244     {
01245       if (!node_set_value (nid->nodes[i],
01246                            &reader, &realign_root,
01247                            i + SET_SEED))
01248         goto out;
01249 
01250       if (i + 1 == nid->n_nodes)
01251         NEXT_EXPECTING_FALSE (&reader);
01252       else
01253         NEXT_EXPECTING_TRUE (&reader);
01254 
01255       ++i;
01256     }
01257 
01258   /* Check that the new values were set */
01259 
01260   reader = realign_root;
01261 
01262   i = 0;
01263   while (i < nid->n_nodes)
01264     {
01265       if (!node_read_value (nid->nodes[i], &reader,
01266                             i + SET_SEED))
01267         goto out;
01268 
01269       if (i + 1 == nid->n_nodes)
01270         NEXT_EXPECTING_FALSE (&reader);
01271       else
01272         NEXT_EXPECTING_TRUE (&reader);
01273 
01274       ++i;
01275     }
01276 
01277   retval = TRUE;
01278 
01279  out:
01280   return retval;
01281 }
01282 
01283 static dbus_bool_t
01284 run_test_delete_values (NodeIterationData *nid)
01285 {
01286   DBusTypeReader reader;
01287   dbus_bool_t retval;
01288   int t;
01289 
01290   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
01291 
01292   retval = FALSE;
01293 
01294   data_block_init_reader_writer (nid->block,
01295                                  &reader, NULL);
01296 
01297   while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
01298     {
01299       /* Right now, deleting only works on array elements.  We delete
01300        * all array elements, and then verify that there aren't any
01301        * left.
01302        */
01303       if (t == DBUS_TYPE_ARRAY)
01304         {
01305           DBusTypeReader array;
01306           int n_elements;
01307           int elem_type;
01308 
01309           _dbus_type_reader_recurse (&reader, &array);
01310           n_elements = 0;
01311           while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
01312             {
01313               n_elements += 1;
01314               _dbus_type_reader_next (&array);
01315             }
01316 
01317           /* reset to start of array */
01318           _dbus_type_reader_recurse (&reader, &array);
01319           _dbus_verbose ("recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d\n",
01320                          reader.value_pos, array.value_pos, array.u.array.start_pos);
01321           while ((elem_type = _dbus_type_reader_get_current_type (&array)) != DBUS_TYPE_INVALID)
01322             {
01323               /* We don't want to always delete from the same part of the array. */
01324               static int cycle = 0;
01325               int elem;
01326 
01327               _dbus_assert (n_elements > 0);
01328 
01329               elem = cycle;
01330               if (elem == 3 || elem >= n_elements) /* end of array */
01331                 elem = n_elements - 1;
01332 
01333               _dbus_verbose ("deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d\n",
01334                              elem, n_elements, _dbus_type_to_string (elem_type),
01335                              cycle, reader.value_pos, array.value_pos);
01336               while (elem > 0)
01337                 {
01338                   if (!_dbus_type_reader_next (&array))
01339                     _dbus_assert_not_reached ("should have had another element\n");
01340                   --elem;
01341                 }
01342 
01343               if (!_dbus_type_reader_delete (&array, &reader))
01344                 goto out;
01345 
01346               n_elements -= 1;
01347 
01348               /* reset */
01349               _dbus_type_reader_recurse (&reader, &array);
01350 
01351               if (cycle > 2)
01352                 cycle = 0;
01353               else
01354                 cycle += 1;
01355             }
01356         }
01357       _dbus_type_reader_next (&reader);
01358     }
01359 
01360   /* Check that there are no array elements left */
01361   data_block_init_reader_writer (nid->block,
01362                                  &reader, NULL);
01363 
01364   while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
01365     {
01366       _dbus_type_reader_next (&reader);
01367     }
01368 
01369   retval = TRUE;
01370 
01371  out:
01372   return retval;
01373 }
01374 
01375 static dbus_bool_t
01376 run_test_nodes_iteration (void *data)
01377 {
01378   NodeIterationData *nid = data;
01379   DBusTypeReader reader;
01380   DBusTypeWriter writer;
01381   int i;
01382   dbus_bool_t retval;
01383 
01384   /* Stuff to do:
01385    * 1. write the value
01386    * 2. strcmp-compare with the signature we built
01387    * 3. read the value
01388    * 4. type-iterate the signature and the value and see if they are the same type-wise
01389    */
01390   retval = FALSE;
01391 
01392   data_block_init_reader_writer (nid->block,
01393                                  &reader, &writer);
01394 
01395   /* DBusTypeWriter assumes it's writing into an existing signature,
01396    * so doesn't add nul on its own. We have to do that.
01397    */
01398   if (!_dbus_string_insert_byte (&nid->block->signature,
01399                                  nid->type_offset, '\0'))
01400     goto out;
01401 
01402   i = 0;
01403   while (i < nid->n_nodes)
01404     {
01405       if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
01406         goto out;
01407 
01408       ++i;
01409     }
01410 
01411   if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
01412                                      &nid->block->signature, nid->type_offset))
01413     {
01414       _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
01415                   _dbus_string_get_const_data (nid->signature),
01416                   _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
01417                   nid->type_offset);
01418       _dbus_assert_not_reached ("wrong signature");
01419     }
01420 
01421   i = 0;
01422   while (i < nid->n_nodes)
01423     {
01424       if (!node_read_value (nid->nodes[i], &reader, i))
01425         goto out;
01426 
01427       if (i + 1 == nid->n_nodes)
01428         NEXT_EXPECTING_FALSE (&reader);
01429       else
01430         NEXT_EXPECTING_TRUE (&reader);
01431 
01432       ++i;
01433     }
01434 
01435   if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
01436     {
01437       /* this set values test uses code from copy and
01438        * values_only_write so would ideally be last so you get a
01439        * simpler test case for problems with copying or values_only
01440        * writing; but it also needs an already-written DataBlock so it
01441        * has to go first. Comment it out if it breaks, and see if the
01442        * later tests also break - debug them first if so.
01443        */
01444       if (!run_test_set_values (nid))
01445         goto out;
01446 
01447       if (!run_test_delete_values (nid))
01448         goto out;
01449 
01450       if (!run_test_copy (nid))
01451         goto out;
01452 
01453       if (!run_test_values_only_write (nid))
01454         goto out;
01455     }
01456 
01457   /* FIXME type-iterate both signature and value and compare the resulting
01458    * tree to the node tree perhaps
01459    */
01460 
01461   retval = TRUE;
01462 
01463  out:
01464 
01465   data_block_reset (nid->block);
01466 
01467   return retval;
01468 }
01469 
01470 static void
01471 run_test_nodes_in_one_configuration (TestTypeNode    **nodes,
01472                                      int               n_nodes,
01473                                      const DBusString *signature,
01474                                      int               byte_order,
01475                                      int               initial_offset)
01476 {
01477   DataBlock block;
01478   NodeIterationData nid;
01479 
01480   if (!data_block_init (&block, byte_order, initial_offset))
01481     _dbus_assert_not_reached ("no memory");
01482 
01483   nid.signature = signature;
01484   nid.block = &block;
01485   nid.type_offset = initial_offset;
01486   nid.nodes = nodes;
01487   nid.n_nodes = n_nodes;
01488 
01489   if (TEST_OOM_HANDLING &&
01490       n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
01491     {
01492       _dbus_test_oom_handling ("running test node",
01493                                run_test_nodes_iteration,
01494                                &nid);
01495     }
01496   else
01497     {
01498       if (!run_test_nodes_iteration (&nid))
01499         _dbus_assert_not_reached ("no memory");
01500     }
01501 
01502   data_block_free (&block);
01503 }
01504 
01505 static void
01506 run_test_nodes (TestTypeNode **nodes,
01507                 int            n_nodes)
01508 {
01509   int i;
01510   DBusString signature;
01511 
01512   if (!_dbus_string_init (&signature))
01513     _dbus_assert_not_reached ("no memory");
01514 
01515   i = 0;
01516   while (i < n_nodes)
01517     {
01518       if (! node_build_signature (nodes[i], &signature))
01519         _dbus_assert_not_reached ("no memory");
01520 
01521       ++i;
01522     }
01523 
01524   _dbus_verbose (">>> test nodes with signature '%s'\n",
01525                  _dbus_string_get_const_data (&signature));
01526 
01527   i = 0;
01528   while (i <= MAX_INITIAL_OFFSET)
01529     {
01530       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
01531                                            DBUS_LITTLE_ENDIAN, i);
01532       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
01533                                            DBUS_BIG_ENDIAN, i);
01534 
01535       ++i;
01536     }
01537 
01538   n_iterations_completed_this_test += 1;
01539   n_iterations_completed_total += 1;
01540 
01541   if (n_iterations_completed_this_test == n_iterations_expected_this_test)
01542     {
01543       fprintf (stderr, " 100%% %d this test (%d cumulative)\n",
01544                n_iterations_completed_this_test,
01545                n_iterations_completed_total);
01546     }
01547   /* this happens to turn out well with mod == 1 */
01548   else if ((n_iterations_completed_this_test %
01549             (int)(n_iterations_expected_this_test / 10.0)) == 1)
01550     {
01551       fprintf (stderr, " %d%% ", (int) (n_iterations_completed_this_test / (double) n_iterations_expected_this_test * 100));
01552     }
01553 
01554   _dbus_string_free (&signature);
01555 }
01556 
01557 #define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
01558 
01559 static TestTypeNode*
01560 value_generator (int *ip)
01561 {
01562   int i = *ip;
01563   const TestTypeNodeClass *child_klass;
01564   const TestTypeNodeClass *container_klass;
01565   TestTypeNode *child;
01566   TestTypeNode *node;
01567 
01568   _dbus_assert (i <= N_VALUES);
01569 
01570   if (i == N_VALUES)
01571     {
01572       return NULL;
01573     }
01574   else if (i < N_BASICS)
01575     {
01576       node = node_new (basic_nodes[i]);
01577     }
01578   else
01579     {
01580       /* imagine an array:
01581        * container 0 of basic 0
01582        * container 0 of basic 1
01583        * container 0 of basic 2
01584        * container 1 of basic 0
01585        * container 1 of basic 1
01586        * container 1 of basic 2
01587        */
01588       i -= N_BASICS;
01589 
01590       container_klass = container_nodes[i / N_BASICS];
01591       child_klass = basic_nodes[i % N_BASICS];
01592 
01593       node = node_new (container_klass);
01594       child = node_new (child_klass);
01595 
01596       node_append_child (node, child);
01597     }
01598 
01599   *ip += 1; /* increment the generator */
01600 
01601   return node;
01602 }
01603 
01604 static void
01605 build_body (TestTypeNode **nodes,
01606             int            n_nodes,
01607             int            byte_order,
01608             DBusString    *signature,
01609             DBusString    *body)
01610 {
01611   int i;
01612   DataBlock block;
01613   DBusTypeReader reader;
01614   DBusTypeWriter writer;
01615 
01616   i = 0;
01617   while (i < n_nodes)
01618     {
01619       if (! node_build_signature (nodes[i], signature))
01620         _dbus_assert_not_reached ("no memory");
01621       
01622       ++i;
01623     }
01624 
01625   if (!data_block_init (&block, byte_order, 0))
01626     _dbus_assert_not_reached ("no memory");
01627   
01628   data_block_init_reader_writer (&block,
01629                                  &reader, &writer);
01630   
01631   /* DBusTypeWriter assumes it's writing into an existing signature,
01632    * so doesn't add nul on its own. We have to do that.
01633    */
01634   if (!_dbus_string_insert_byte (&block.signature,
01635                                  0, '\0'))
01636     _dbus_assert_not_reached ("no memory");
01637 
01638   i = 0;
01639   while (i < n_nodes)
01640     {
01641       if (!node_write_value (nodes[i], &block, &writer, i))
01642         _dbus_assert_not_reached ("no memory");
01643 
01644       ++i;
01645     }
01646 
01647   if (!_dbus_string_copy_len (&block.body, 0,
01648                               _dbus_string_get_length (&block.body) - N_FENCE_BYTES,
01649                               body, 0))
01650     _dbus_assert_not_reached ("oom");
01651 
01652   data_block_free (&block);  
01653 }
01654 
01655 dbus_bool_t
01656 dbus_internal_do_not_use_generate_bodies (int           sequence,
01657                                           int           byte_order,
01658                                           DBusString   *signature,
01659                                           DBusString   *body)
01660 {
01661   TestTypeNode *nodes[1];
01662   int i;
01663   int n_nodes;
01664 
01665   nodes[0] = value_generator (&sequence);
01666 
01667   if (nodes[0] == NULL)
01668     return FALSE;
01669 
01670   n_nodes = 1;
01671   
01672   build_body (nodes, n_nodes, byte_order, signature, body);
01673 
01674 
01675   i = 0;
01676   while (i < n_nodes)
01677     {
01678       node_destroy (nodes[i]);
01679       ++i;
01680     }
01681   
01682   return TRUE;
01683 }
01684 
01685 static void
01686 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
01687                                       int                      n_nested)
01688 {
01689   TestTypeNode *root;
01690   TestTypeNode *container;
01691   TestTypeNode *child;
01692   int i;
01693 
01694   root = node_new (container_klass);
01695   container = root;
01696   for (i = 1; i < n_nested; i++)
01697     {
01698       child = node_new (container_klass);
01699       node_append_child (container, child);
01700       container = child;
01701     }
01702 
01703   /* container should now be the most-nested container */
01704 
01705   i = 0;
01706   while ((child = value_generator (&i)))
01707     {
01708       node_append_child (container, child);
01709 
01710       run_test_nodes (&root, 1);
01711 
01712       _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
01713       node_destroy (child);
01714     }
01715 
01716   node_destroy (root);
01717 }
01718 
01719 static void
01720 start_next_test (const char *format,
01721                  int         expected)
01722 {
01723   n_iterations_completed_this_test = 0;
01724   n_iterations_expected_this_test = expected;
01725 
01726   fprintf (stderr, ">>> >>> ");
01727   fprintf (stderr, format,
01728            n_iterations_expected_this_test);
01729 }
01730 
01731 static void
01732 make_and_run_test_nodes (void)
01733 {
01734   int i, j, k, m;
01735 
01736   /* We try to do this in order of "complicatedness" so that test
01737    * failures tend to show up in the simplest test case that
01738    * demonstrates the failure.  There are also some tests that run
01739    * more than once for this reason, first while going through simple
01740    * cases, second while going through a broader range of complex
01741    * cases.
01742    */
01743   /* Each basic node. The basic nodes should include:
01744    *
01745    * - each fixed-size type (in such a way that it has different values each time,
01746    *                         so we can tell if we mix two of them up)
01747    * - strings of various lengths
01748    * - object path
01749    * - signature
01750    */
01751   /* Each container node. The container nodes should include:
01752    *
01753    *  struct with 1 and 2 copies of the contained item
01754    *  array with 0, 1, 2 copies of the contained item
01755    *  variant
01756    */
01757   /*  Let a "value" be a basic node, or a container containing a single basic node.
01758    *  Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
01759    *  When iterating through all values to make combinations, do the basic types
01760    *  first and the containers second.
01761    */
01762   /* Each item is shown with its number of iterations to complete so
01763    * we can keep a handle on this unit test
01764    */
01765 
01766   /* FIXME test just an empty body, no types at all */
01767 
01768   start_next_test ("Each value by itself %d iterations\n", N_VALUES);
01769   {
01770     TestTypeNode *node;
01771     i = 0;
01772     while ((node = value_generator (&i)))
01773       {
01774         run_test_nodes (&node, 1);
01775 
01776         node_destroy (node);
01777       }
01778   }
01779 
01780   start_next_test ("Each value by itself with arrays as blocks %d iterations\n", N_VALUES);
01781   arrays_write_fixed_in_blocks = TRUE;
01782   {
01783     TestTypeNode *node;
01784     i = 0;
01785     while ((node = value_generator (&i)))
01786       {
01787         run_test_nodes (&node, 1);
01788 
01789         node_destroy (node);
01790       }
01791   }
01792   arrays_write_fixed_in_blocks = FALSE;
01793 
01794   start_next_test ("All values in one big toplevel %d iteration\n", 1);
01795   {
01796     TestTypeNode *nodes[N_VALUES];
01797 
01798     i = 0;
01799     while ((nodes[i] = value_generator (&i)))
01800       ;
01801 
01802     run_test_nodes (nodes, N_VALUES);
01803 
01804     for (i = 0; i < N_VALUES; i++)
01805       node_destroy (nodes[i]);
01806   }
01807 
01808   start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n",
01809                    N_VALUES * N_VALUES);
01810   {
01811     TestTypeNode *nodes[2];
01812 
01813     i = 0;
01814     while ((nodes[0] = value_generator (&i)))
01815       {
01816         j = 0;
01817         while ((nodes[1] = value_generator (&j)))
01818           {
01819             run_test_nodes (nodes, 2);
01820 
01821             node_destroy (nodes[1]);
01822           }
01823 
01824         node_destroy (nodes[0]);
01825       }
01826   }
01827 
01828   start_next_test ("Each container containing each value %d iterations\n",
01829                    N_CONTAINERS * N_VALUES);
01830   for (i = 0; i < N_CONTAINERS; i++)
01831     {
01832       const TestTypeNodeClass *container_klass = container_nodes[i];
01833 
01834       make_and_run_values_inside_container (container_klass, 1);
01835     }
01836 
01837   start_next_test ("Each container containing each value with arrays as blocks %d iterations\n",
01838                    N_CONTAINERS * N_VALUES);
01839   arrays_write_fixed_in_blocks = TRUE;
01840   for (i = 0; i < N_CONTAINERS; i++)
01841     {
01842       const TestTypeNodeClass *container_klass = container_nodes[i];
01843 
01844       make_and_run_values_inside_container (container_klass, 1);
01845     }
01846   arrays_write_fixed_in_blocks = FALSE;
01847 
01848   start_next_test ("Each container of same container of each value %d iterations\n",
01849                    N_CONTAINERS * N_VALUES);
01850   for (i = 0; i < N_CONTAINERS; i++)
01851     {
01852       const TestTypeNodeClass *container_klass = container_nodes[i];
01853 
01854       make_and_run_values_inside_container (container_klass, 2);
01855     }
01856 
01857   start_next_test ("Each container of same container of same container of each value %d iterations\n",
01858                    N_CONTAINERS * N_VALUES);
01859   for (i = 0; i < N_CONTAINERS; i++)
01860     {
01861       const TestTypeNodeClass *container_klass = container_nodes[i];
01862 
01863       make_and_run_values_inside_container (container_klass, 3);
01864     }
01865 
01866   start_next_test ("Each value,value pair inside a struct %d iterations\n",
01867                    N_VALUES * N_VALUES);
01868   {
01869     TestTypeNode *val1, *val2;
01870     TestTypeNode *node;
01871 
01872     node = node_new (&struct_1_class);
01873 
01874     i = 0;
01875     while ((val1 = value_generator (&i)))
01876       {
01877         j = 0;
01878         while ((val2 = value_generator (&j)))
01879           {
01880             TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01881 
01882             node_append_child (node, val1);
01883             node_append_child (node, val2);
01884 
01885             run_test_nodes (&node, 1);
01886 
01887             _dbus_list_clear (&container->children);
01888             node_destroy (val2);
01889           }
01890         node_destroy (val1);
01891       }
01892     node_destroy (node);
01893   }
01894 
01895   start_next_test ("All values in one big struct %d iteration\n",
01896                    1);
01897   {
01898     TestTypeNode *node;
01899     TestTypeNode *child;
01900 
01901     node = node_new (&struct_1_class);
01902 
01903     i = 0;
01904     while ((child = value_generator (&i)))
01905       node_append_child (node, child);
01906 
01907     run_test_nodes (&node, 1);
01908 
01909     node_destroy (node);
01910   }
01911 
01912   start_next_test ("Each value in a large array %d iterations\n",
01913                    N_VALUES);
01914   {
01915     TestTypeNode *val;
01916     TestTypeNode *node;
01917 
01918     node = node_new (&array_9_class);
01919 
01920     i = 0;
01921     while ((val = value_generator (&i)))
01922       {
01923         TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
01924 
01925         node_append_child (node, val);
01926 
01927         run_test_nodes (&node, 1);
01928 
01929         _dbus_list_clear (&container->children);
01930         node_destroy (val);
01931       }
01932 
01933     node_destroy (node);
01934   }
01935 
01936   start_next_test ("Each container of each container of each value %d iterations\n",
01937                    N_CONTAINERS * N_CONTAINERS * N_VALUES);
01938   for (i = 0; i < N_CONTAINERS; i++)
01939     {
01940       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
01941       TestTypeNode *outer_container = node_new (outer_container_klass);
01942 
01943       for (j = 0; j < N_CONTAINERS; j++)
01944         {
01945           TestTypeNode *child;
01946           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
01947           TestTypeNode *inner_container = node_new (inner_container_klass);
01948 
01949           node_append_child (outer_container, inner_container);
01950 
01951           m = 0;
01952           while ((child = value_generator (&m)))
01953             {
01954               node_append_child (inner_container, child);
01955 
01956               run_test_nodes (&outer_container, 1);
01957 
01958               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
01959               node_destroy (child);
01960             }
01961           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
01962           node_destroy (inner_container);
01963         }
01964       node_destroy (outer_container);
01965     }
01966 
01967   start_next_test ("Each container of each container of each container of each value %d iterations\n",
01968                    N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
01969   for (i = 0; i < N_CONTAINERS; i++)
01970     {
01971       const TestTypeNodeClass *outer_container_klass = container_nodes[i];
01972       TestTypeNode *outer_container = node_new (outer_container_klass);
01973 
01974       for (j = 0; j < N_CONTAINERS; j++)
01975         {
01976           const TestTypeNodeClass *inner_container_klass = container_nodes[j];
01977           TestTypeNode *inner_container = node_new (inner_container_klass);
01978 
01979           node_append_child (outer_container, inner_container);
01980 
01981           for (k = 0; k < N_CONTAINERS; k++)
01982             {
01983               TestTypeNode *child;
01984               const TestTypeNodeClass *center_container_klass = container_nodes[k];
01985               TestTypeNode *center_container = node_new (center_container_klass);
01986 
01987               node_append_child (inner_container, center_container);
01988 
01989               m = 0;
01990               while ((child = value_generator (&m)))
01991                 {
01992                   node_append_child (center_container, child);
01993 
01994                   run_test_nodes (&outer_container, 1);
01995 
01996                   _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
01997                   node_destroy (child);
01998                 }
01999               _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
02000               node_destroy (center_container);
02001             }
02002           _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
02003           node_destroy (inner_container);
02004         }
02005       node_destroy (outer_container);
02006     }
02007 
02008 #if 0
02009   /* This one takes a really long time, so comment it out for now */
02010   start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
02011                    N_VALUES * N_VALUES * N_VALUES);
02012   {
02013     TestTypeNode *nodes[3];
02014 
02015     i = 0;
02016     while ((nodes[0] = value_generator (&i)))
02017       {
02018         j = 0;
02019         while ((nodes[1] = value_generator (&j)))
02020           {
02021             k = 0;
02022             while ((nodes[2] = value_generator (&k)))
02023               {
02024                 run_test_nodes (nodes, 3);
02025 
02026                 node_destroy (nodes[2]);
02027               }
02028             node_destroy (nodes[1]);
02029           }
02030         node_destroy (nodes[0]);
02031       }
02032   }
02033 #endif /* #if 0 expensive test */
02034 
02035   fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
02036            n_iterations_completed_total);
02037   fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
02038            MAX_INITIAL_OFFSET);
02039   fprintf (stderr, "out of memory handling %s tested\n",
02040            TEST_OOM_HANDLING ? "was" : "was not");
02041 }
02042 
02043 dbus_bool_t
02044 _dbus_marshal_recursive_test (void)
02045 {
02046   make_and_run_test_nodes ();
02047 
02048   return TRUE;
02049 }
02050 
02051 /*
02052  *
02053  *
02054  *         Implementations of each type node class
02055  *
02056  *
02057  *
02058  */
02059 #define MAX_MULTI_COUNT 5
02060 
02061 #define SAMPLE_INT16           1234
02062 #define SAMPLE_INT16_ALTERNATE 6785
02063 static dbus_int16_t
02064 int16_from_seed (int seed)
02065 {
02066   /* Generate an integer value that's predictable from seed.  We could
02067    * just use seed itself, but that would only ever touch one byte of
02068    * the int so would miss some kinds of bug.
02069    */
02070   dbus_int16_t v;
02071 
02072   v = 42; /* just to quiet compiler afaik */
02073   switch (seed % 5)
02074     {
02075     case 0:
02076       v = SAMPLE_INT16;
02077       break;
02078     case 1:
02079       v = SAMPLE_INT16_ALTERNATE;
02080       break;
02081     case 2:
02082       v = -1;
02083       break;
02084     case 3:
02085       v = _DBUS_INT16_MAX;
02086       break;
02087     case 4:
02088       v = 1;
02089       break;
02090     }
02091 
02092   if (seed > 1)
02093     v *= seed; /* wraps around eventually, which is fine */
02094 
02095   return v;
02096 }
02097 
02098 static dbus_bool_t
02099 int16_write_value (TestTypeNode   *node,
02100                    DataBlock      *block,
02101                    DBusTypeWriter *writer,
02102                    int             seed)
02103 {
02104   /* also used for uint16 */
02105   dbus_int16_t v;
02106 
02107   v = int16_from_seed (seed);
02108 
02109   return _dbus_type_writer_write_basic (writer,
02110                                         node->klass->typecode,
02111                                         &v);
02112 }
02113 
02114 static dbus_bool_t
02115 int16_read_value (TestTypeNode   *node,
02116                   DBusTypeReader *reader,
02117                   int             seed)
02118 {
02119   /* also used for uint16 */
02120   dbus_int16_t v;
02121 
02122   check_expected_type (reader, node->klass->typecode);
02123 
02124   _dbus_type_reader_read_basic (reader,
02125                                 (dbus_int16_t*) &v);
02126 
02127   _dbus_assert (v == int16_from_seed (seed));
02128 
02129   return TRUE;
02130 }
02131 
02132 static dbus_bool_t
02133 int16_set_value (TestTypeNode   *node,
02134                  DBusTypeReader *reader,
02135                  DBusTypeReader *realign_root,
02136                  int             seed)
02137 {
02138   /* also used for uint16 */
02139   dbus_int16_t v;
02140 
02141   v = int16_from_seed (seed);
02142 
02143   return _dbus_type_reader_set_basic (reader,
02144                                       &v,
02145                                       realign_root);
02146 }
02147 
02148 static dbus_bool_t
02149 int16_write_multi (TestTypeNode   *node,
02150                    DataBlock      *block,
02151                    DBusTypeWriter *writer,
02152                    int             seed,
02153                    int             count)
02154 {
02155   /* also used for uint16 */
02156   dbus_int16_t values[MAX_MULTI_COUNT];
02157   dbus_int16_t *v_ARRAY_INT16 = values;
02158   int i;
02159 
02160   for (i = 0; i < count; ++i)
02161     values[i] = int16_from_seed (seed + i);
02162 
02163   return _dbus_type_writer_write_fixed_multi (writer,
02164                                               node->klass->typecode,
02165                                               &v_ARRAY_INT16, count);
02166 }
02167 
02168 static dbus_bool_t
02169 int16_read_multi (TestTypeNode   *node,
02170                   DBusTypeReader *reader,
02171                   int             seed,
02172                   int             count)
02173 {
02174   /* also used for uint16 */
02175   dbus_int16_t *values;
02176   int n_elements;
02177   int i;
02178 
02179   check_expected_type (reader, node->klass->typecode);
02180 
02181   _dbus_type_reader_read_fixed_multi (reader,
02182                                       &values,
02183                                       &n_elements);
02184 
02185   if (n_elements != count)
02186     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
02187   _dbus_assert (n_elements == count);
02188 
02189   for (i = 0; i < count; i++)
02190     _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
02191                                                       (const unsigned char*)values + (i * 2))) ==
02192                   int16_from_seed (seed + i));
02193 
02194   return TRUE;
02195 }
02196 
02197 
02198 #define SAMPLE_INT32           12345678
02199 #define SAMPLE_INT32_ALTERNATE 53781429
02200 static dbus_int32_t
02201 int32_from_seed (int seed)
02202 {
02203   /* Generate an integer value that's predictable from seed.  We could
02204    * just use seed itself, but that would only ever touch one byte of
02205    * the int so would miss some kinds of bug.
02206    */
02207   dbus_int32_t v;
02208 
02209   v = 42; /* just to quiet compiler afaik */
02210   switch (seed % 5)
02211     {
02212     case 0:
02213       v = SAMPLE_INT32;
02214       break;
02215     case 1:
02216       v = SAMPLE_INT32_ALTERNATE;
02217       break;
02218     case 2:
02219       v = -1;
02220       break;
02221     case 3:
02222       v = _DBUS_INT_MAX;
02223       break;
02224     case 4:
02225       v = 1;
02226       break;
02227     }
02228 
02229   if (seed > 1)
02230     v *= seed; /* wraps around eventually, which is fine */
02231 
02232   return v;
02233 }
02234 
02235 static dbus_bool_t
02236 int32_write_value (TestTypeNode   *node,
02237                    DataBlock      *block,
02238                    DBusTypeWriter *writer,
02239                    int             seed)
02240 {
02241   /* also used for uint32 */
02242   dbus_int32_t v;
02243 
02244   v = int32_from_seed (seed);
02245 
02246   return _dbus_type_writer_write_basic (writer,
02247                                         node->klass->typecode,
02248                                         &v);
02249 }
02250 
02251 static dbus_bool_t
02252 int32_read_value (TestTypeNode   *node,
02253                   DBusTypeReader *reader,
02254                   int             seed)
02255 {
02256   /* also used for uint32 */
02257   dbus_int32_t v;
02258 
02259   check_expected_type (reader, node->klass->typecode);
02260 
02261   _dbus_type_reader_read_basic (reader,
02262                                 (dbus_int32_t*) &v);
02263 
02264   _dbus_assert (v == int32_from_seed (seed));
02265 
02266   return TRUE;
02267 }
02268 
02269 static dbus_bool_t
02270 int32_set_value (TestTypeNode   *node,
02271                  DBusTypeReader *reader,
02272                  DBusTypeReader *realign_root,
02273                  int             seed)
02274 {
02275   /* also used for uint32 */
02276   dbus_int32_t v;
02277 
02278   v = int32_from_seed (seed);
02279 
02280   return _dbus_type_reader_set_basic (reader,
02281                                       &v,
02282                                       realign_root);
02283 }
02284 
02285 static dbus_bool_t
02286 int32_write_multi (TestTypeNode   *node,
02287                    DataBlock      *block,
02288                    DBusTypeWriter *writer,
02289                    int             seed,
02290                    int             count)
02291 {
02292   /* also used for uint32 */
02293   dbus_int32_t values[MAX_MULTI_COUNT];
02294   dbus_int32_t *v_ARRAY_INT32 = values;
02295   int i;
02296 
02297   for (i = 0; i < count; ++i)
02298     values[i] = int32_from_seed (seed + i);
02299 
02300   return _dbus_type_writer_write_fixed_multi (writer,
02301                                               node->klass->typecode,
02302                                               &v_ARRAY_INT32, count);
02303 }
02304 
02305 static dbus_bool_t
02306 int32_read_multi (TestTypeNode   *node,
02307                   DBusTypeReader *reader,
02308                   int             seed,
02309                   int             count)
02310 {
02311   /* also used for uint32 */
02312   dbus_int32_t *values;
02313   int n_elements;
02314   int i;
02315 
02316   check_expected_type (reader, node->klass->typecode);
02317 
02318   _dbus_type_reader_read_fixed_multi (reader,
02319                                       &values,
02320                                       &n_elements);
02321 
02322   if (n_elements != count)
02323     _dbus_warn ("got %d elements expected %d\n", n_elements, count);
02324   _dbus_assert (n_elements == count);
02325 
02326   for (i = 0; i < count; i++)
02327     _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order,
02328                                              (const unsigned char*)values + (i * 4))) ==
02329                   int32_from_seed (seed + i));
02330 
02331   return TRUE;
02332 }
02333 
02334 #ifdef DBUS_HAVE_INT64
02335 static dbus_int64_t
02336 int64_from_seed (int seed)
02337 {
02338   dbus_int32_t v32;
02339   dbus_int64_t v;
02340 
02341   v32 = int32_from_seed (seed);
02342 
02343   v = - (dbus_int32_t) ~ v32;
02344   v |= (((dbus_int64_t)v32) << 32);
02345 
02346   return v;
02347 }
02348 #endif
02349 
02350 static dbus_bool_t
02351 int64_write_value (TestTypeNode   *node,
02352                    DataBlock      *block,
02353                    DBusTypeWriter *writer,
02354                    int             seed)
02355 {
02356 #ifdef DBUS_HAVE_INT64
02357   /* also used for uint64 */
02358   dbus_int64_t v;
02359 
02360   v = int64_from_seed (seed);
02361 
02362   return _dbus_type_writer_write_basic (writer,
02363                                         node->klass->typecode,
02364                                         &v);
02365 #else
02366   return TRUE;
02367 #endif
02368 }
02369 
02370 static dbus_bool_t
02371 int64_read_value (TestTypeNode   *node,
02372                   DBusTypeReader *reader,
02373                   int             seed)
02374 {
02375 #ifdef DBUS_HAVE_INT64
02376   /* also used for uint64 */
02377   dbus_int64_t v;
02378 
02379   check_expected_type (reader, node->klass->typecode);
02380 
02381   _dbus_type_reader_read_basic (reader,
02382                                 (dbus_int64_t*) &v);
02383 
02384   _dbus_assert (v == int64_from_seed (seed));
02385 
02386   return TRUE;
02387 #else
02388   return TRUE;
02389 #endif
02390 }
02391 
02392 static dbus_bool_t
02393 int64_set_value (TestTypeNode   *node,
02394                  DBusTypeReader *reader,
02395                  DBusTypeReader *realign_root,
02396                  int             seed)
02397 {
02398 #ifdef DBUS_HAVE_INT64
02399   /* also used for uint64 */
02400   dbus_int64_t v;
02401 
02402   v = int64_from_seed (seed);
02403 
02404   return _dbus_type_reader_set_basic (reader,
02405                                       &v,
02406                                       realign_root);
02407 #else
02408   return TRUE;
02409 #endif
02410 }
02411 
02412 #define MAX_SAMPLE_STRING_LEN 10
02413 static void
02414 string_from_seed (char *buf,
02415                   int   len,
02416                   int   seed)
02417 {
02418   int i;
02419   unsigned char v;
02420 
02421   _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
02422 
02423   /* vary the length slightly, though we also have multiple string
02424    * value types for this, varying it here tests the set_value code
02425    */
02426   switch (seed % 3)
02427     {
02428     case 1:
02429       len += 2;
02430       break;
02431     case 2:
02432       len -= 2;
02433       break;
02434     }
02435   if (len < 0)
02436     len = 0;
02437 
02438   v = (unsigned char) ('A' + seed);
02439 
02440   i = 0;
02441   while (i < len)
02442     {
02443       if (v < 'A' || v > 'z')
02444         v = 'A';
02445 
02446       buf[i] = v;
02447 
02448       v += 1;
02449       ++i;
02450     }
02451 
02452   buf[i] = '\0';
02453 }
02454 
02455 static dbus_bool_t
02456 string_write_value (TestTypeNode   *node,
02457                     DataBlock      *block,
02458                     DBusTypeWriter *writer,
02459                     int             seed)
02460 {
02461   char buf[MAX_SAMPLE_STRING_LEN + 1]="";
02462   const char *v_string = buf;
02463 
02464 
02465   string_from_seed (buf, node->klass->subclass_detail,
02466                     seed);
02467 
02468   return _dbus_type_writer_write_basic (writer,
02469                                         node->klass->typecode,
02470                                         &v_string);
02471 }
02472 
02473 static dbus_bool_t
02474 string_read_value (TestTypeNode   *node,
02475                    DBusTypeReader *reader,
02476                    int             seed)
02477 {
02478   const char *v;
02479   char buf[MAX_SAMPLE_STRING_LEN + 1];
02480   v = buf;
02481 
02482   check_expected_type (reader, node->klass->typecode);
02483 
02484   _dbus_type_reader_read_basic (reader,
02485                                 (const char **) &v);
02486 
02487   string_from_seed (buf, node->klass->subclass_detail,
02488                     seed);
02489 
02490   if (strcmp (buf, v) != 0)
02491     {
02492       _dbus_warn ("read string '%s' expected '%s'\n",
02493                   v, buf);
02494       _dbus_assert_not_reached ("test failed");
02495     }
02496 
02497   return TRUE;
02498 }
02499 
02500 static dbus_bool_t
02501 string_set_value (TestTypeNode   *node,
02502                   DBusTypeReader *reader,
02503                   DBusTypeReader *realign_root,
02504                   int             seed)
02505 {
02506   char buf[MAX_SAMPLE_STRING_LEN + 1];
02507   const char *v_string = buf;
02508 
02509   string_from_seed (buf, node->klass->subclass_detail,
02510                     seed);
02511 
02512 #if RECURSIVE_MARSHAL_WRITE_TRACE
02513  {
02514    const char *old;
02515    _dbus_type_reader_read_basic (reader, &old);
02516    _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
02517                   v_string, strlen (v_string), old, strlen (old));
02518  }
02519 #endif
02520 
02521   return _dbus_type_reader_set_basic (reader,
02522                                       &v_string,
02523                                       realign_root);
02524 }
02525 
02526 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
02527 
02528 static dbus_bool_t
02529 bool_write_value (TestTypeNode   *node,
02530                   DataBlock      *block,
02531                   DBusTypeWriter *writer,
02532                   int             seed)
02533 {
02534   dbus_bool_t v;
02535 
02536   v = BOOL_FROM_SEED (seed);
02537 
02538   return _dbus_type_writer_write_basic (writer,
02539                                         node->klass->typecode,
02540                                         &v);
02541 }
02542 
02543 static dbus_bool_t
02544 bool_read_value (TestTypeNode   *node,
02545                  DBusTypeReader *reader,
02546                  int             seed)
02547 {
02548   dbus_bool_t v;
02549 
02550   check_expected_type (reader, node->klass->typecode);
02551 
02552   _dbus_type_reader_read_basic (reader,
02553                                 (unsigned char*) &v);
02554 
02555   _dbus_assert (v == BOOL_FROM_SEED (seed));
02556 
02557   return TRUE;
02558 }
02559 
02560 static dbus_bool_t
02561 bool_set_value (TestTypeNode   *node,
02562                 DBusTypeReader *reader,
02563                 DBusTypeReader *realign_root,
02564                 int             seed)
02565 {
02566   dbus_bool_t v;
02567 
02568   v = BOOL_FROM_SEED (seed);
02569 
02570   return _dbus_type_reader_set_basic (reader,
02571                                       &v,
02572                                       realign_root);
02573 }
02574 
02575 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
02576 
02577 static dbus_bool_t
02578 byte_write_value (TestTypeNode   *node,
02579                   DataBlock      *block,
02580                   DBusTypeWriter *writer,
02581                   int             seed)
02582 {
02583   unsigned char v;
02584 
02585   v = BYTE_FROM_SEED (seed);
02586 
02587   return _dbus_type_writer_write_basic (writer,
02588                                         node->klass->typecode,
02589                                         &v);
02590 }
02591 
02592 static dbus_bool_t
02593 byte_read_value (TestTypeNode   *node,
02594                  DBusTypeReader *reader,
02595                  int             seed)
02596 {
02597   unsigned char v;
02598 
02599   check_expected_type (reader, node->klass->typecode);
02600 
02601   _dbus_type_reader_read_basic (reader,
02602                                 (unsigned char*) &v);
02603 
02604   _dbus_assert (v == BYTE_FROM_SEED (seed));
02605 
02606   return TRUE;
02607 }
02608 
02609 
02610 static dbus_bool_t
02611 byte_set_value (TestTypeNode   *node,
02612                 DBusTypeReader *reader,
02613                 DBusTypeReader *realign_root,
02614                 int             seed)
02615 {
02616   unsigned char v;
02617 
02618   v = BYTE_FROM_SEED (seed);
02619 
02620   return _dbus_type_reader_set_basic (reader,
02621                                       &v,
02622                                       realign_root);
02623 }
02624 
02625 static double
02626 double_from_seed (int seed)
02627 {
02628   return SAMPLE_INT32 * (double) seed + 0.3;
02629 }
02630 
02631 static dbus_bool_t
02632 double_write_value (TestTypeNode   *node,
02633                     DataBlock      *block,
02634                     DBusTypeWriter *writer,
02635                     int             seed)
02636 {
02637   double v;
02638 
02639   v = double_from_seed (seed);
02640 
02641   return _dbus_type_writer_write_basic (writer,
02642                                         node->klass->typecode,
02643                                         &v);
02644 }
02645 
02646 static dbus_bool_t
02647 double_read_value (TestTypeNode   *node,
02648                    DBusTypeReader *reader,
02649                    int             seed)
02650 {
02651   double v;
02652   double expected;
02653 
02654   check_expected_type (reader, node->klass->typecode);
02655 
02656   _dbus_type_reader_read_basic (reader,
02657                                 (double*) &v);
02658 
02659   expected = double_from_seed (seed);
02660 
02661   if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
02662     {
02663 #ifdef DBUS_HAVE_INT64
02664       _dbus_warn ("Expected double %g got %g\n bits = 0x%llx vs.\n bits = 0x%llx)\n",
02665                   expected, v,
02666                   *(dbus_uint64_t*)(char*)&expected,
02667                   *(dbus_uint64_t*)(char*)&v);
02668 #endif
02669       _dbus_assert_not_reached ("test failed");
02670     }
02671 
02672   return TRUE;
02673 }
02674 
02675 static dbus_bool_t
02676 double_set_value (TestTypeNode   *node,
02677                 DBusTypeReader *reader,
02678                 DBusTypeReader *realign_root,
02679                 int             seed)
02680 {
02681   double v;
02682 
02683   v = double_from_seed (seed);
02684 
02685   return _dbus_type_reader_set_basic (reader,
02686                                       &v,
02687                                       realign_root);
02688 }
02689 
02690 #define MAX_SAMPLE_OBJECT_PATH_LEN 10
02691 static void
02692 object_path_from_seed (char *buf,
02693                        int   seed)
02694 {
02695   int i;
02696   unsigned char v;
02697   int len;
02698 
02699   len = seed % 9;
02700   _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
02701 
02702   v = (unsigned char) ('A' + seed);
02703 
02704   if (len < 2)
02705     {
02706       buf[0] = '/';
02707       i = 1;
02708     }
02709   else
02710     {
02711       i = 0;
02712       while (i + 1 < len)
02713         {
02714           if (v < 'A' || v > 'z')
02715             v = 'A';
02716 
02717           buf[i] = '/';
02718           ++i;
02719           buf[i] = v;
02720           ++i;
02721           
02722           v += 1;
02723         }
02724     }
02725 
02726   buf[i] = '\0';
02727 }
02728 
02729 static dbus_bool_t
02730 object_path_write_value (TestTypeNode   *node,
02731                          DataBlock      *block,
02732                          DBusTypeWriter *writer,
02733                          int             seed)
02734 {
02735   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02736   const char *v_string = buf;
02737 
02738   object_path_from_seed (buf, seed);
02739 
02740   return _dbus_type_writer_write_basic (writer,
02741                                         node->klass->typecode,
02742                                         &v_string);
02743 }
02744 
02745 static dbus_bool_t
02746 object_path_read_value (TestTypeNode   *node,
02747                         DBusTypeReader *reader,
02748                         int             seed)
02749 {
02750   const char *v;
02751   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02752 
02753   check_expected_type (reader, node->klass->typecode);
02754 
02755   _dbus_type_reader_read_basic (reader,
02756                                 (const char **) &v);
02757 
02758   object_path_from_seed (buf, seed);
02759 
02760   if (strcmp (buf, v) != 0)
02761     {
02762       _dbus_warn ("read object path '%s' expected '%s'\n",
02763                   v, buf);
02764       _dbus_assert_not_reached ("test failed");
02765     }
02766 
02767   return TRUE;
02768 }
02769 
02770 static dbus_bool_t
02771 object_path_set_value (TestTypeNode   *node,
02772                        DBusTypeReader *reader,
02773                        DBusTypeReader *realign_root,
02774                        int             seed)
02775 {
02776   char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
02777   const char *v_string = buf;
02778 
02779   object_path_from_seed (buf, seed);
02780 
02781   return _dbus_type_reader_set_basic (reader,
02782                                       &v_string,
02783                                       realign_root);
02784 }
02785 
02786 #define MAX_SAMPLE_SIGNATURE_LEN 10
02787 static void
02788 signature_from_seed (char *buf,
02789                      int   seed)
02790 {
02791   /* try to avoid ascending, descending, or alternating length to help find bugs */
02792   const char *sample_signatures[] = {
02793     "asax"
02794     "",
02795     "asau(xxxx)",
02796     "x",
02797     "ai",
02798     "a(ii)"
02799   };
02800 
02801   strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
02802 }
02803 
02804 static dbus_bool_t
02805 signature_write_value (TestTypeNode   *node,
02806                        DataBlock      *block,
02807                        DBusTypeWriter *writer,
02808                        int             seed)
02809 {
02810   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02811   const char *v_string = buf;
02812 
02813   signature_from_seed (buf, seed);
02814 
02815   return _dbus_type_writer_write_basic (writer,
02816                                         node->klass->typecode,
02817                                         &v_string);
02818 }
02819 
02820 static dbus_bool_t
02821 signature_read_value (TestTypeNode   *node,
02822                       DBusTypeReader *reader,
02823                       int             seed)
02824 {
02825   const char *v;
02826   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02827 
02828   check_expected_type (reader, node->klass->typecode);
02829 
02830   _dbus_type_reader_read_basic (reader,
02831                                 (const char **) &v);
02832 
02833   signature_from_seed (buf, seed);
02834 
02835   if (strcmp (buf, v) != 0)
02836     {
02837       _dbus_warn ("read signature value '%s' expected '%s'\n",
02838                   v, buf);
02839       _dbus_assert_not_reached ("test failed");
02840     }
02841 
02842   return TRUE;
02843 }
02844 
02845 
02846 static dbus_bool_t
02847 signature_set_value (TestTypeNode   *node,
02848                      DBusTypeReader *reader,
02849                      DBusTypeReader *realign_root,
02850                      int             seed)
02851 {
02852   char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
02853   const char *v_string = buf;
02854 
02855   signature_from_seed (buf, seed);
02856 
02857   return _dbus_type_reader_set_basic (reader,
02858                                       &v_string,
02859                                       realign_root);
02860 }
02861 
02862 static dbus_bool_t
02863 struct_write_value (TestTypeNode   *node,
02864                     DataBlock      *block,
02865                     DBusTypeWriter *writer,
02866                     int             seed)
02867 {
02868   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02869   DataBlockState saved;
02870   DBusTypeWriter sub;
02871   int i;
02872   int n_copies;
02873 
02874   n_copies = node->klass->subclass_detail;
02875 
02876   _dbus_assert (container->children != NULL);
02877 
02878   data_block_save (block, &saved);
02879 
02880   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
02881                                   NULL, 0,
02882                                   &sub))
02883     return FALSE;
02884 
02885   i = 0;
02886   while (i < n_copies)
02887     {
02888       DBusList *link;
02889 
02890       link = _dbus_list_get_first_link (&container->children);
02891       while (link != NULL)
02892         {
02893           TestTypeNode *child = link->data;
02894           DBusList *next = _dbus_list_get_next_link (&container->children, link);
02895 
02896           if (!node_write_value (child, block, &sub, seed + i))
02897             {
02898               data_block_restore (block, &saved);
02899               return FALSE;
02900             }
02901 
02902           link = next;
02903         }
02904 
02905       ++i;
02906     }
02907 
02908   if (!_dbus_type_writer_unrecurse (writer, &sub))
02909     {
02910       data_block_restore (block, &saved);
02911       return FALSE;
02912     }
02913 
02914   return TRUE;
02915 }
02916 
02917 static dbus_bool_t
02918 struct_read_or_set_value (TestTypeNode   *node,
02919                           DBusTypeReader *reader,
02920                           DBusTypeReader *realign_root,
02921                           int             seed)
02922 {
02923   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02924   DBusTypeReader sub;
02925   int i;
02926   int n_copies;
02927 
02928   n_copies = node->klass->subclass_detail;
02929 
02930   check_expected_type (reader, DBUS_TYPE_STRUCT);
02931 
02932   _dbus_type_reader_recurse (reader, &sub);
02933 
02934   i = 0;
02935   while (i < n_copies)
02936     {
02937       DBusList *link;
02938 
02939       link = _dbus_list_get_first_link (&container->children);
02940       while (link != NULL)
02941         {
02942           TestTypeNode *child = link->data;
02943           DBusList *next = _dbus_list_get_next_link (&container->children, link);
02944 
02945           if (realign_root == NULL)
02946             {
02947               if (!node_read_value (child, &sub, seed + i))
02948                 return FALSE;
02949             }
02950           else
02951             {
02952               if (!node_set_value (child, &sub, realign_root, seed + i))
02953                 return FALSE;
02954             }
02955 
02956           if (i == (n_copies - 1) && next == NULL)
02957             NEXT_EXPECTING_FALSE (&sub);
02958           else
02959             NEXT_EXPECTING_TRUE (&sub);
02960 
02961           link = next;
02962         }
02963 
02964       ++i;
02965     }
02966 
02967   return TRUE;
02968 }
02969 
02970 static dbus_bool_t
02971 struct_read_value (TestTypeNode   *node,
02972                    DBusTypeReader *reader,
02973                    int             seed)
02974 {
02975   return struct_read_or_set_value (node, reader, NULL, seed);
02976 }
02977 
02978 static dbus_bool_t
02979 struct_set_value (TestTypeNode   *node,
02980                   DBusTypeReader *reader,
02981                   DBusTypeReader *realign_root,
02982                   int             seed)
02983 {
02984   return struct_read_or_set_value (node, reader, realign_root, seed);
02985 }
02986 
02987 static dbus_bool_t
02988 struct_build_signature (TestTypeNode   *node,
02989                         DBusString     *str)
02990 {
02991   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
02992   int i;
02993   int orig_len;
02994   int n_copies;
02995 
02996   n_copies = node->klass->subclass_detail;
02997 
02998   orig_len = _dbus_string_get_length (str);
02999 
03000   if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
03001     goto oom;
03002 
03003   i = 0;
03004   while (i < n_copies)
03005     {
03006       DBusList *link;
03007 
03008       link = _dbus_list_get_first_link (&container->children);
03009       while (link != NULL)
03010         {
03011           TestTypeNode *child = link->data;
03012           DBusList *next = _dbus_list_get_next_link (&container->children, link);
03013 
03014           if (!node_build_signature (child, str))
03015             goto oom;
03016 
03017           link = next;
03018         }
03019 
03020       ++i;
03021     }
03022 
03023   if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
03024     goto oom;
03025 
03026   return TRUE;
03027 
03028  oom:
03029   _dbus_string_set_length (str, orig_len);
03030   return FALSE;
03031 }
03032 
03033 static dbus_bool_t
03034 array_write_value (TestTypeNode   *node,
03035                    DataBlock      *block,
03036                    DBusTypeWriter *writer,
03037                    int             seed)
03038 {
03039   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03040   DataBlockState saved;
03041   DBusTypeWriter sub;
03042   DBusString element_signature;
03043   int i;
03044   int n_copies;
03045   int element_type;
03046   TestTypeNode *child;
03047 
03048   n_copies = node->klass->subclass_detail;
03049 
03050   _dbus_assert (container->children != NULL);
03051 
03052   data_block_save (block, &saved);
03053 
03054   if (!_dbus_string_init (&element_signature))
03055     return FALSE;
03056 
03057   child = _dbus_list_get_first (&container->children);
03058 
03059   if (!node_build_signature (child,
03060                              &element_signature))
03061     goto oom;
03062 
03063   element_type = _dbus_first_type_in_signature (&element_signature, 0);
03064 
03065   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
03066                                   &element_signature, 0,
03067                                   &sub))
03068     goto oom;
03069 
03070   if (arrays_write_fixed_in_blocks &&
03071       dbus_type_is_fixed (element_type) &&
03072       child->klass->write_multi)
03073     {
03074       if (!node_write_multi (child, block, &sub, seed, n_copies))
03075         goto oom;
03076     }
03077   else
03078     {
03079       i = 0;
03080       while (i < n_copies)
03081         {
03082           DBusList *link;
03083 
03084           link = _dbus_list_get_first_link (&container->children);
03085           while (link != NULL)
03086             {
03087               TestTypeNode *child = link->data;
03088               DBusList *next = _dbus_list_get_next_link (&container->children, link);
03089 
03090               if (!node_write_value (child, block, &sub, seed + i))
03091                 goto oom;
03092 
03093               link = next;
03094             }
03095 
03096           ++i;
03097         }
03098     }
03099 
03100   if (!_dbus_type_writer_unrecurse (writer, &sub))
03101     goto oom;
03102 
03103   _dbus_string_free (&element_signature);
03104   return TRUE;
03105 
03106  oom:
03107   data_block_restore (block, &saved);
03108   _dbus_string_free (&element_signature);
03109   return FALSE;
03110 }
03111 
03112 static dbus_bool_t
03113 array_read_or_set_value (TestTypeNode   *node,
03114                          DBusTypeReader *reader,
03115                          DBusTypeReader *realign_root,
03116                          int             seed)
03117 {
03118   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03119   DBusTypeReader sub;
03120   int i;
03121   int n_copies;
03122   TestTypeNode *child;
03123 
03124   n_copies = node->klass->subclass_detail;
03125 
03126   check_expected_type (reader, DBUS_TYPE_ARRAY);
03127 
03128   child = _dbus_list_get_first (&container->children);
03129 
03130   if (n_copies > 0)
03131     {
03132       _dbus_type_reader_recurse (reader, &sub);
03133 
03134       if (realign_root == NULL && arrays_write_fixed_in_blocks &&
03135           dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
03136           child->klass->read_multi)
03137         {
03138           if (!node_read_multi (child, &sub, seed, n_copies))
03139             return FALSE;
03140         }
03141       else
03142         {
03143           i = 0;
03144           while (i < n_copies)
03145             {
03146               DBusList *link;
03147 
03148               link = _dbus_list_get_first_link (&container->children);
03149               while (link != NULL)
03150                 {
03151                   TestTypeNode *child = link->data;
03152                   DBusList *next = _dbus_list_get_next_link (&container->children, link);
03153 
03154                   _dbus_assert (child->klass->typecode ==
03155                                 _dbus_type_reader_get_element_type (reader));
03156 
03157                   if (realign_root == NULL)
03158                     {
03159                       if (!node_read_value (child, &sub, seed + i))
03160                         return FALSE;
03161                     }
03162                   else
03163                     {
03164                       if (!node_set_value (child, &sub, realign_root, seed + i))
03165                         return FALSE;
03166                     }
03167 
03168                   if (i == (n_copies - 1) && next == NULL)
03169                     NEXT_EXPECTING_FALSE (&sub);
03170                   else
03171                     NEXT_EXPECTING_TRUE (&sub);
03172 
03173                   link = next;
03174                 }
03175 
03176               ++i;
03177             }
03178         }
03179     }
03180 
03181   return TRUE;
03182 }
03183 
03184 static dbus_bool_t
03185 array_read_value (TestTypeNode   *node,
03186                   DBusTypeReader *reader,
03187                   int             seed)
03188 {
03189   return array_read_or_set_value (node, reader, NULL, seed);
03190 }
03191 
03192 static dbus_bool_t
03193 array_set_value (TestTypeNode   *node,
03194                  DBusTypeReader *reader,
03195                  DBusTypeReader *realign_root,
03196                  int             seed)
03197 {
03198   return array_read_or_set_value (node, reader, realign_root, seed);
03199 }
03200 
03201 static dbus_bool_t
03202 array_build_signature (TestTypeNode   *node,
03203                        DBusString     *str)
03204 {
03205   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03206   int orig_len;
03207 
03208   orig_len = _dbus_string_get_length (str);
03209 
03210   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
03211     goto oom;
03212 
03213   if (!node_build_signature (_dbus_list_get_first (&container->children),
03214                              str))
03215     goto oom;
03216 
03217   return TRUE;
03218 
03219  oom:
03220   _dbus_string_set_length (str, orig_len);
03221   return FALSE;
03222 }
03223 
03224  /* 10 is random just to add another seed that we use in the suite */
03225 #define VARIANT_SEED 10
03226 
03227 static dbus_bool_t
03228 variant_write_value (TestTypeNode   *node,
03229                      DataBlock      *block,
03230                      DBusTypeWriter *writer,
03231                      int             seed)
03232 {
03233   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03234   DataBlockState saved;
03235   DBusTypeWriter sub;
03236   DBusString content_signature;
03237   TestTypeNode *child;
03238 
03239   _dbus_assert (container->children != NULL);
03240   _dbus_assert (_dbus_list_length_is_one (&container->children));
03241 
03242   child = _dbus_list_get_first (&container->children);
03243 
03244   data_block_save (block, &saved);
03245 
03246   if (!_dbus_string_init (&content_signature))
03247     return FALSE;
03248 
03249   if (!node_build_signature (child,
03250                              &content_signature))
03251     goto oom;
03252 
03253   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
03254                                   &content_signature, 0,
03255                                   &sub))
03256     goto oom;
03257 
03258   if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
03259     goto oom;
03260 
03261   if (!_dbus_type_writer_unrecurse (writer, &sub))
03262     goto oom;
03263 
03264   _dbus_string_free (&content_signature);
03265   return TRUE;
03266 
03267  oom:
03268   data_block_restore (block, &saved);
03269   _dbus_string_free (&content_signature);
03270   return FALSE;
03271 }
03272 
03273 static dbus_bool_t
03274 variant_read_or_set_value (TestTypeNode   *node,
03275                            DBusTypeReader *reader,
03276                            DBusTypeReader *realign_root,
03277                            int             seed)
03278 {
03279   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03280   DBusTypeReader sub;
03281   TestTypeNode *child;
03282 
03283   _dbus_assert (container->children != NULL);
03284   _dbus_assert (_dbus_list_length_is_one (&container->children));
03285 
03286   child = _dbus_list_get_first (&container->children);
03287 
03288   check_expected_type (reader, DBUS_TYPE_VARIANT);
03289 
03290   _dbus_type_reader_recurse (reader, &sub);
03291 
03292   if (realign_root == NULL)
03293     {
03294       if (!node_read_value (child, &sub, seed + VARIANT_SEED))
03295         return FALSE;
03296     }
03297   else
03298     {
03299       if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
03300         return FALSE;
03301     }
03302 
03303   NEXT_EXPECTING_FALSE (&sub);
03304 
03305   return TRUE;
03306 }
03307 
03308 static dbus_bool_t
03309 variant_read_value (TestTypeNode   *node,
03310                     DBusTypeReader *reader,
03311                     int             seed)
03312 {
03313   return variant_read_or_set_value (node, reader, NULL, seed);
03314 }
03315 
03316 static dbus_bool_t
03317 variant_set_value (TestTypeNode   *node,
03318                    DBusTypeReader *reader,
03319                    DBusTypeReader *realign_root,
03320                    int             seed)
03321 {
03322   return variant_read_or_set_value (node, reader, realign_root, seed);
03323 }
03324 
03325 static dbus_bool_t
03326 dict_write_value (TestTypeNode   *node,
03327                   DataBlock      *block,
03328                   DBusTypeWriter *writer,
03329                   int             seed)
03330 {
03331   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03332   DataBlockState saved;
03333   DBusTypeWriter sub;
03334   DBusString entry_value_signature;
03335   DBusString dict_entry_signature;
03336   int i;
03337   int n_entries;
03338   int entry_value_type;
03339   TestTypeNode *child;
03340 
03341   n_entries = node->klass->subclass_detail;
03342 
03343   _dbus_assert (container->children != NULL);
03344 
03345   data_block_save (block, &saved);
03346 
03347   if (!_dbus_string_init (&entry_value_signature))
03348     return FALSE;
03349 
03350   if (!_dbus_string_init (&dict_entry_signature))
03351     {
03352       _dbus_string_free (&entry_value_signature);
03353       return FALSE;
03354     }
03355   
03356   child = _dbus_list_get_first (&container->children);
03357 
03358   if (!node_build_signature (child,
03359                              &entry_value_signature))
03360     goto oom;
03361 
03362   if (!_dbus_string_append (&dict_entry_signature,
03363                             DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
03364                             DBUS_TYPE_INT32_AS_STRING))
03365     goto oom;
03366 
03367   if (!_dbus_string_copy (&entry_value_signature, 0,
03368                           &dict_entry_signature,
03369                           _dbus_string_get_length (&dict_entry_signature)))
03370     goto oom;
03371 
03372   if (!_dbus_string_append_byte (&dict_entry_signature,
03373                                  DBUS_DICT_ENTRY_END_CHAR))
03374     goto oom;
03375   
03376   entry_value_type = _dbus_first_type_in_signature (&entry_value_signature, 0);
03377   
03378   if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
03379                                   &dict_entry_signature, 0,
03380                                   &sub))
03381     goto oom;
03382 
03383   i = 0;
03384   while (i < n_entries)
03385     {
03386       DBusTypeWriter entry_sub;
03387       dbus_int32_t key;
03388 
03389       if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
03390                                       NULL, 0,
03391                                       &entry_sub))
03392         goto oom;
03393 
03394       key = int32_from_seed (seed + i);
03395 
03396       if (!_dbus_type_writer_write_basic (&entry_sub,
03397                                           DBUS_TYPE_INT32,
03398                                           &key))
03399         goto oom;
03400       
03401       if (!node_write_value (child, block, &entry_sub, seed + i))
03402         goto oom;
03403 
03404       if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
03405         goto oom;
03406       
03407       ++i;
03408     }
03409 
03410   if (!_dbus_type_writer_unrecurse (writer, &sub))
03411     goto oom;
03412   
03413   _dbus_string_free (&entry_value_signature);
03414   _dbus_string_free (&dict_entry_signature);
03415   return TRUE;
03416 
03417  oom:
03418   data_block_restore (block, &saved);
03419   _dbus_string_free (&entry_value_signature);
03420   _dbus_string_free (&dict_entry_signature);
03421   return FALSE;
03422 }
03423 
03424 static dbus_bool_t
03425 dict_read_or_set_value (TestTypeNode   *node,
03426                         DBusTypeReader *reader,
03427                         DBusTypeReader *realign_root,
03428                         int             seed)
03429 {
03430   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03431   DBusTypeReader sub;
03432   int i;
03433   int n_entries;
03434   TestTypeNode *child;
03435 
03436   n_entries = node->klass->subclass_detail;
03437 
03438   check_expected_type (reader, DBUS_TYPE_ARRAY);
03439 
03440   child = _dbus_list_get_first (&container->children);
03441 
03442   if (n_entries > 0)
03443     {
03444       _dbus_type_reader_recurse (reader, &sub);
03445 
03446       check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
03447       
03448       i = 0;
03449       while (i < n_entries)
03450         {
03451           DBusTypeReader entry_sub;
03452 
03453           check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
03454           
03455           _dbus_type_reader_recurse (&sub, &entry_sub);
03456           
03457           if (realign_root == NULL)
03458             {
03459               dbus_int32_t v;
03460               
03461               check_expected_type (&entry_sub, DBUS_TYPE_INT32);
03462 
03463               _dbus_type_reader_read_basic (&entry_sub,
03464                                             (dbus_int32_t*) &v);
03465 
03466               _dbus_assert (v == int32_from_seed (seed + i));
03467 
03468               NEXT_EXPECTING_TRUE (&entry_sub);
03469               
03470               if (!node_read_value (child, &entry_sub, seed + i))
03471                 return FALSE;
03472 
03473               NEXT_EXPECTING_FALSE (&entry_sub);
03474             }
03475           else
03476             {
03477               dbus_int32_t v;
03478               
03479               v = int32_from_seed (seed + i);
03480               
03481               if (!_dbus_type_reader_set_basic (&entry_sub,
03482                                                 &v,
03483                                                 realign_root))
03484                 return FALSE;
03485 
03486               NEXT_EXPECTING_TRUE (&entry_sub);
03487               
03488               if (!node_set_value (child, &entry_sub, realign_root, seed + i))
03489                 return FALSE;
03490 
03491               NEXT_EXPECTING_FALSE (&entry_sub);
03492             }
03493           
03494           if (i == (n_entries - 1))
03495             NEXT_EXPECTING_FALSE (&sub);
03496           else
03497             NEXT_EXPECTING_TRUE (&sub);
03498 
03499           ++i;
03500         }
03501     }
03502 
03503   return TRUE;
03504 }
03505 
03506 static dbus_bool_t
03507 dict_read_value (TestTypeNode   *node,
03508                  DBusTypeReader *reader,
03509                  int             seed)
03510 {
03511   return dict_read_or_set_value (node, reader, NULL, seed);
03512 }
03513 
03514 static dbus_bool_t
03515 dict_set_value (TestTypeNode   *node,
03516                 DBusTypeReader *reader,
03517                 DBusTypeReader *realign_root,
03518                 int             seed)
03519 {
03520   return dict_read_or_set_value (node, reader, realign_root, seed);
03521 }
03522 
03523 static dbus_bool_t
03524 dict_build_signature (TestTypeNode   *node,
03525                       DBusString     *str)
03526 {
03527   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03528   int orig_len;
03529 
03530   orig_len = _dbus_string_get_length (str);
03531 
03532   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
03533     goto oom;
03534 
03535   if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
03536     goto oom;
03537   
03538   if (!node_build_signature (_dbus_list_get_first (&container->children),
03539                              str))
03540     goto oom;
03541 
03542   if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
03543     goto oom;
03544 
03545   return TRUE;
03546 
03547  oom:
03548   _dbus_string_set_length (str, orig_len);
03549   return FALSE;
03550 }
03551 
03552 static void
03553 container_destroy (TestTypeNode *node)
03554 {
03555   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
03556   DBusList *link;
03557 
03558   link = _dbus_list_get_first_link (&container->children);
03559   while (link != NULL)
03560     {
03561       TestTypeNode *child = link->data;
03562       DBusList *next = _dbus_list_get_next_link (&container->children, link);
03563 
03564       node_destroy (child);
03565 
03566       _dbus_list_free_link (link);
03567 
03568       link = next;
03569     }
03570 }
03571 
03572 #endif /* DBUS_BUILD_TESTS */

Generated on Fri Sep 30 19:45:35 2005 for D-BUS by  doxygen 1.4.4