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