D-Bus
1.6.8
|
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->eight.first32 = 0; 00042 value->eight.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->eight.first32 == rhs->eight.first32 && 00063 lhs->eight.second32 == rhs->eight.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 if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL || 01928 atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1) 01929 { 01930 fprintf (stderr, "skipping remaining marshal-recursive tests, " 01931 "run with DBUS_TEST_SLOW=1 (or more) to enable\n"); 01932 goto out; 01933 } 01934 01935 start_next_test ("Each container of each container of each value %d iterations\n", 01936 N_CONTAINERS * N_CONTAINERS * N_VALUES); 01937 for (i = 0; i < N_CONTAINERS; i++) 01938 { 01939 const TestTypeNodeClass *outer_container_klass = container_nodes[i]; 01940 TestTypeNode *outer_container = node_new (outer_container_klass); 01941 01942 for (j = 0; j < N_CONTAINERS; j++) 01943 { 01944 TestTypeNode *child; 01945 const TestTypeNodeClass *inner_container_klass = container_nodes[j]; 01946 TestTypeNode *inner_container = node_new (inner_container_klass); 01947 01948 node_append_child (outer_container, inner_container); 01949 01950 m = 0; 01951 while ((child = value_generator (&m))) 01952 { 01953 node_append_child (inner_container, child); 01954 01955 run_test_nodes (&outer_container, 1); 01956 01957 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children); 01958 node_destroy (child); 01959 } 01960 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children); 01961 node_destroy (inner_container); 01962 } 01963 node_destroy (outer_container); 01964 } 01965 01966 start_next_test ("Each container of each container of each container of each value %d iterations\n", 01967 N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES); 01968 for (i = 0; i < N_CONTAINERS; i++) 01969 { 01970 const TestTypeNodeClass *outer_container_klass = container_nodes[i]; 01971 TestTypeNode *outer_container = node_new (outer_container_klass); 01972 01973 for (j = 0; j < N_CONTAINERS; j++) 01974 { 01975 const TestTypeNodeClass *inner_container_klass = container_nodes[j]; 01976 TestTypeNode *inner_container = node_new (inner_container_klass); 01977 01978 node_append_child (outer_container, inner_container); 01979 01980 for (k = 0; k < N_CONTAINERS; k++) 01981 { 01982 TestTypeNode *child; 01983 const TestTypeNodeClass *center_container_klass = container_nodes[k]; 01984 TestTypeNode *center_container = node_new (center_container_klass); 01985 01986 node_append_child (inner_container, center_container); 01987 01988 m = 0; 01989 while ((child = value_generator (&m))) 01990 { 01991 node_append_child (center_container, child); 01992 01993 run_test_nodes (&outer_container, 1); 01994 01995 _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children); 01996 node_destroy (child); 01997 } 01998 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children); 01999 node_destroy (center_container); 02000 } 02001 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children); 02002 node_destroy (inner_container); 02003 } 02004 node_destroy (outer_container); 02005 } 02006 02007 /* This one takes a really long time (10 minutes on a Core2), so only enable 02008 * it if you're really sure */ 02009 if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2) 02010 { 02011 fprintf (stderr, "skipping really slow marshal-recursive test, " 02012 "run with DBUS_TEST_SLOW=2 (or more) to enable\n"); 02013 goto out; 02014 } 02015 02016 start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n", 02017 N_VALUES * N_VALUES * N_VALUES); 02018 { 02019 TestTypeNode *nodes[3]; 02020 02021 i = 0; 02022 while ((nodes[0] = value_generator (&i))) 02023 { 02024 j = 0; 02025 while ((nodes[1] = value_generator (&j))) 02026 { 02027 k = 0; 02028 while ((nodes[2] = value_generator (&k))) 02029 { 02030 run_test_nodes (nodes, 3); 02031 02032 node_destroy (nodes[2]); 02033 } 02034 node_destroy (nodes[1]); 02035 } 02036 node_destroy (nodes[0]); 02037 } 02038 } 02039 02040 out: 02041 fprintf (stderr, "%d total iterations of recursive marshaling tests\n", 02042 n_iterations_completed_total); 02043 fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n", 02044 MAX_INITIAL_OFFSET); 02045 fprintf (stderr, "out of memory handling %s tested\n", 02046 TEST_OOM_HANDLING ? "was" : "was not"); 02047 } 02048 02049 dbus_bool_t 02050 _dbus_marshal_recursive_test (void) 02051 { 02052 make_and_run_test_nodes (); 02053 02054 return TRUE; 02055 } 02056 02057 /* 02058 * 02059 * 02060 * Implementations of each type node class 02061 * 02062 * 02063 * 02064 */ 02065 #define MAX_MULTI_COUNT 5 02066 02067 #define SAMPLE_INT16 1234 02068 #define SAMPLE_INT16_ALTERNATE 6785 02069 static dbus_int16_t 02070 int16_from_seed (int seed) 02071 { 02072 /* Generate an integer value that's predictable from seed. We could 02073 * just use seed itself, but that would only ever touch one byte of 02074 * the int so would miss some kinds of bug. 02075 */ 02076 dbus_int16_t v; 02077 02078 v = 42; /* just to quiet compiler afaik */ 02079 switch (seed % 5) 02080 { 02081 case 0: 02082 v = SAMPLE_INT16; 02083 break; 02084 case 1: 02085 v = SAMPLE_INT16_ALTERNATE; 02086 break; 02087 case 2: 02088 v = -1; 02089 break; 02090 case 3: 02091 v = _DBUS_INT16_MAX; 02092 break; 02093 case 4: 02094 v = 1; 02095 break; 02096 } 02097 02098 if (seed > 1) 02099 v *= seed; /* wraps around eventually, which is fine */ 02100 02101 return v; 02102 } 02103 02104 static dbus_bool_t 02105 int16_write_value (TestTypeNode *node, 02106 DataBlock *block, 02107 DBusTypeWriter *writer, 02108 int seed) 02109 { 02110 /* also used for uint16 */ 02111 dbus_int16_t v; 02112 02113 v = int16_from_seed (seed); 02114 02115 return _dbus_type_writer_write_basic (writer, 02116 node->klass->typecode, 02117 &v); 02118 } 02119 02120 static dbus_bool_t 02121 int16_read_value (TestTypeNode *node, 02122 DBusTypeReader *reader, 02123 int seed) 02124 { 02125 /* also used for uint16 */ 02126 dbus_int16_t v; 02127 02128 check_expected_type (reader, node->klass->typecode); 02129 02130 _dbus_type_reader_read_basic (reader, 02131 (dbus_int16_t*) &v); 02132 02133 _dbus_assert (v == int16_from_seed (seed)); 02134 02135 return TRUE; 02136 } 02137 02138 static dbus_bool_t 02139 int16_set_value (TestTypeNode *node, 02140 DBusTypeReader *reader, 02141 DBusTypeReader *realign_root, 02142 int seed) 02143 { 02144 /* also used for uint16 */ 02145 dbus_int16_t v; 02146 02147 v = int16_from_seed (seed); 02148 02149 return _dbus_type_reader_set_basic (reader, 02150 &v, 02151 realign_root); 02152 } 02153 02154 static dbus_bool_t 02155 int16_write_multi (TestTypeNode *node, 02156 DataBlock *block, 02157 DBusTypeWriter *writer, 02158 int seed, 02159 int count) 02160 { 02161 /* also used for uint16 */ 02162 dbus_int16_t values[MAX_MULTI_COUNT]; 02163 dbus_int16_t *v_ARRAY_INT16 = values; 02164 int i; 02165 02166 for (i = 0; i < count; ++i) 02167 values[i] = int16_from_seed (seed + i); 02168 02169 return _dbus_type_writer_write_fixed_multi (writer, 02170 node->klass->typecode, 02171 &v_ARRAY_INT16, count); 02172 } 02173 02174 static dbus_bool_t 02175 int16_read_multi (TestTypeNode *node, 02176 DBusTypeReader *reader, 02177 int seed, 02178 int count) 02179 { 02180 /* also used for uint16 */ 02181 dbus_int16_t *values; 02182 int n_elements; 02183 int i; 02184 02185 check_expected_type (reader, node->klass->typecode); 02186 02187 _dbus_type_reader_read_fixed_multi (reader, 02188 &values, 02189 &n_elements); 02190 02191 if (n_elements != count) 02192 _dbus_warn ("got %d elements expected %d\n", n_elements, count); 02193 _dbus_assert (n_elements == count); 02194 02195 for (i = 0; i < count; i++) 02196 _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order, 02197 (const unsigned char*)values + (i * 2))) == 02198 int16_from_seed (seed + i)); 02199 02200 return TRUE; 02201 } 02202 02203 02204 #define SAMPLE_INT32 12345678 02205 #define SAMPLE_INT32_ALTERNATE 53781429 02206 static dbus_int32_t 02207 int32_from_seed (int seed) 02208 { 02209 /* Generate an integer value that's predictable from seed. We could 02210 * just use seed itself, but that would only ever touch one byte of 02211 * the int so would miss some kinds of bug. 02212 */ 02213 dbus_int32_t v; 02214 02215 v = 42; /* just to quiet compiler afaik */ 02216 switch (seed % 5) 02217 { 02218 case 0: 02219 v = SAMPLE_INT32; 02220 break; 02221 case 1: 02222 v = SAMPLE_INT32_ALTERNATE; 02223 break; 02224 case 2: 02225 v = -1; 02226 break; 02227 case 3: 02228 v = _DBUS_INT_MAX; 02229 break; 02230 case 4: 02231 v = 1; 02232 break; 02233 } 02234 02235 if (seed > 1) 02236 v *= seed; /* wraps around eventually, which is fine */ 02237 02238 return v; 02239 } 02240 02241 static dbus_bool_t 02242 int32_write_value (TestTypeNode *node, 02243 DataBlock *block, 02244 DBusTypeWriter *writer, 02245 int seed) 02246 { 02247 /* also used for uint32 */ 02248 dbus_int32_t v; 02249 02250 v = int32_from_seed (seed); 02251 02252 return _dbus_type_writer_write_basic (writer, 02253 node->klass->typecode, 02254 &v); 02255 } 02256 02257 static dbus_bool_t 02258 int32_read_value (TestTypeNode *node, 02259 DBusTypeReader *reader, 02260 int seed) 02261 { 02262 /* also used for uint32 */ 02263 dbus_int32_t v; 02264 02265 check_expected_type (reader, node->klass->typecode); 02266 02267 _dbus_type_reader_read_basic (reader, 02268 (dbus_int32_t*) &v); 02269 02270 _dbus_assert (v == int32_from_seed (seed)); 02271 02272 return TRUE; 02273 } 02274 02275 static dbus_bool_t 02276 int32_set_value (TestTypeNode *node, 02277 DBusTypeReader *reader, 02278 DBusTypeReader *realign_root, 02279 int seed) 02280 { 02281 /* also used for uint32 */ 02282 dbus_int32_t v; 02283 02284 v = int32_from_seed (seed); 02285 02286 return _dbus_type_reader_set_basic (reader, 02287 &v, 02288 realign_root); 02289 } 02290 02291 static dbus_bool_t 02292 int32_write_multi (TestTypeNode *node, 02293 DataBlock *block, 02294 DBusTypeWriter *writer, 02295 int seed, 02296 int count) 02297 { 02298 /* also used for uint32 */ 02299 dbus_int32_t values[MAX_MULTI_COUNT]; 02300 dbus_int32_t *v_ARRAY_INT32 = values; 02301 int i; 02302 02303 for (i = 0; i < count; ++i) 02304 values[i] = int32_from_seed (seed + i); 02305 02306 return _dbus_type_writer_write_fixed_multi (writer, 02307 node->klass->typecode, 02308 &v_ARRAY_INT32, count); 02309 } 02310 02311 static dbus_bool_t 02312 int32_read_multi (TestTypeNode *node, 02313 DBusTypeReader *reader, 02314 int seed, 02315 int count) 02316 { 02317 /* also used for uint32 */ 02318 dbus_int32_t *values; 02319 int n_elements; 02320 int i; 02321 02322 check_expected_type (reader, node->klass->typecode); 02323 02324 _dbus_type_reader_read_fixed_multi (reader, 02325 &values, 02326 &n_elements); 02327 02328 if (n_elements != count) 02329 _dbus_warn ("got %d elements expected %d\n", n_elements, count); 02330 _dbus_assert (n_elements == count); 02331 02332 for (i = 0; i < count; i++) 02333 _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order, 02334 (const unsigned char*)values + (i * 4))) == 02335 int32_from_seed (seed + i)); 02336 02337 return TRUE; 02338 } 02339 02340 #ifdef DBUS_HAVE_INT64 02341 static dbus_int64_t 02342 int64_from_seed (int seed) 02343 { 02344 dbus_int32_t v32; 02345 dbus_int64_t v; 02346 02347 v32 = int32_from_seed (seed); 02348 02349 v = - (dbus_int32_t) ~ v32; 02350 v |= (((dbus_int64_t)v32) << 32); 02351 02352 return v; 02353 } 02354 #endif 02355 02356 static dbus_bool_t 02357 int64_write_value (TestTypeNode *node, 02358 DataBlock *block, 02359 DBusTypeWriter *writer, 02360 int seed) 02361 { 02362 #ifdef DBUS_HAVE_INT64 02363 /* also used for uint64 */ 02364 dbus_int64_t v; 02365 02366 v = int64_from_seed (seed); 02367 02368 return _dbus_type_writer_write_basic (writer, 02369 node->klass->typecode, 02370 &v); 02371 #else 02372 return TRUE; 02373 #endif 02374 } 02375 02376 static dbus_bool_t 02377 int64_read_value (TestTypeNode *node, 02378 DBusTypeReader *reader, 02379 int seed) 02380 { 02381 #ifdef DBUS_HAVE_INT64 02382 /* also used for uint64 */ 02383 dbus_int64_t v; 02384 02385 check_expected_type (reader, node->klass->typecode); 02386 02387 _dbus_type_reader_read_basic (reader, 02388 (dbus_int64_t*) &v); 02389 02390 _dbus_assert (v == int64_from_seed (seed)); 02391 02392 return TRUE; 02393 #else 02394 return TRUE; 02395 #endif 02396 } 02397 02398 static dbus_bool_t 02399 int64_set_value (TestTypeNode *node, 02400 DBusTypeReader *reader, 02401 DBusTypeReader *realign_root, 02402 int seed) 02403 { 02404 #ifdef DBUS_HAVE_INT64 02405 /* also used for uint64 */ 02406 dbus_int64_t v; 02407 02408 v = int64_from_seed (seed); 02409 02410 return _dbus_type_reader_set_basic (reader, 02411 &v, 02412 realign_root); 02413 #else 02414 return TRUE; 02415 #endif 02416 } 02417 02418 #define MAX_SAMPLE_STRING_LEN 10 02419 static void 02420 string_from_seed (char *buf, 02421 int len, 02422 int seed) 02423 { 02424 int i; 02425 unsigned char v; 02426 02427 _dbus_assert (len < MAX_SAMPLE_STRING_LEN); 02428 02429 /* vary the length slightly, though we also have multiple string 02430 * value types for this, varying it here tests the set_value code 02431 */ 02432 switch (seed % 3) 02433 { 02434 case 1: 02435 len += 2; 02436 break; 02437 case 2: 02438 len -= 2; 02439 break; 02440 } 02441 if (len < 0) 02442 len = 0; 02443 02444 v = (unsigned char) ('A' + seed); 02445 02446 i = 0; 02447 while (i < len) 02448 { 02449 if (v < 'A' || v > 'z') 02450 v = 'A'; 02451 02452 buf[i] = v; 02453 02454 v += 1; 02455 ++i; 02456 } 02457 02458 buf[i] = '\0'; 02459 } 02460 02461 static dbus_bool_t 02462 string_write_value (TestTypeNode *node, 02463 DataBlock *block, 02464 DBusTypeWriter *writer, 02465 int seed) 02466 { 02467 char buf[MAX_SAMPLE_STRING_LEN + 1]=""; 02468 const char *v_string = buf; 02469 02470 02471 string_from_seed (buf, node->klass->subclass_detail, 02472 seed); 02473 02474 return _dbus_type_writer_write_basic (writer, 02475 node->klass->typecode, 02476 &v_string); 02477 } 02478 02479 static dbus_bool_t 02480 string_read_value (TestTypeNode *node, 02481 DBusTypeReader *reader, 02482 int seed) 02483 { 02484 const char *v; 02485 char buf[MAX_SAMPLE_STRING_LEN + 1]; 02486 v = buf; 02487 02488 check_expected_type (reader, node->klass->typecode); 02489 02490 _dbus_type_reader_read_basic (reader, 02491 (const char **) &v); 02492 02493 string_from_seed (buf, node->klass->subclass_detail, 02494 seed); 02495 02496 if (strcmp (buf, v) != 0) 02497 { 02498 _dbus_warn ("read string '%s' expected '%s'\n", 02499 v, buf); 02500 _dbus_assert_not_reached ("test failed"); 02501 } 02502 02503 return TRUE; 02504 } 02505 02506 static dbus_bool_t 02507 string_set_value (TestTypeNode *node, 02508 DBusTypeReader *reader, 02509 DBusTypeReader *realign_root, 02510 int seed) 02511 { 02512 char buf[MAX_SAMPLE_STRING_LEN + 1]; 02513 const char *v_string = buf; 02514 02515 string_from_seed (buf, node->klass->subclass_detail, 02516 seed); 02517 02518 #if RECURSIVE_MARSHAL_WRITE_TRACE 02519 { 02520 const char *old; 02521 _dbus_type_reader_read_basic (reader, &old); 02522 _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n", 02523 v_string, strlen (v_string), old, strlen (old)); 02524 } 02525 #endif 02526 02527 return _dbus_type_reader_set_basic (reader, 02528 &v_string, 02529 realign_root); 02530 } 02531 02532 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2)) 02533 02534 static dbus_bool_t 02535 bool_write_value (TestTypeNode *node, 02536 DataBlock *block, 02537 DBusTypeWriter *writer, 02538 int seed) 02539 { 02540 dbus_bool_t v; 02541 02542 v = BOOL_FROM_SEED (seed); 02543 02544 return _dbus_type_writer_write_basic (writer, 02545 node->klass->typecode, 02546 &v); 02547 } 02548 02549 static dbus_bool_t 02550 bool_read_value (TestTypeNode *node, 02551 DBusTypeReader *reader, 02552 int seed) 02553 { 02554 dbus_bool_t v; 02555 02556 check_expected_type (reader, node->klass->typecode); 02557 02558 _dbus_type_reader_read_basic (reader, 02559 (unsigned char*) &v); 02560 02561 _dbus_assert (v == BOOL_FROM_SEED (seed)); 02562 02563 return TRUE; 02564 } 02565 02566 static dbus_bool_t 02567 bool_set_value (TestTypeNode *node, 02568 DBusTypeReader *reader, 02569 DBusTypeReader *realign_root, 02570 int seed) 02571 { 02572 dbus_bool_t v; 02573 02574 v = BOOL_FROM_SEED (seed); 02575 02576 return _dbus_type_reader_set_basic (reader, 02577 &v, 02578 realign_root); 02579 } 02580 02581 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed)) 02582 02583 static dbus_bool_t 02584 byte_write_value (TestTypeNode *node, 02585 DataBlock *block, 02586 DBusTypeWriter *writer, 02587 int seed) 02588 { 02589 unsigned char v; 02590 02591 v = BYTE_FROM_SEED (seed); 02592 02593 return _dbus_type_writer_write_basic (writer, 02594 node->klass->typecode, 02595 &v); 02596 } 02597 02598 static dbus_bool_t 02599 byte_read_value (TestTypeNode *node, 02600 DBusTypeReader *reader, 02601 int seed) 02602 { 02603 unsigned char v; 02604 02605 check_expected_type (reader, node->klass->typecode); 02606 02607 _dbus_type_reader_read_basic (reader, 02608 (unsigned char*) &v); 02609 02610 _dbus_assert (v == BYTE_FROM_SEED (seed)); 02611 02612 return TRUE; 02613 } 02614 02615 02616 static dbus_bool_t 02617 byte_set_value (TestTypeNode *node, 02618 DBusTypeReader *reader, 02619 DBusTypeReader *realign_root, 02620 int seed) 02621 { 02622 unsigned char v; 02623 02624 v = BYTE_FROM_SEED (seed); 02625 02626 return _dbus_type_reader_set_basic (reader, 02627 &v, 02628 realign_root); 02629 } 02630 02631 static double 02632 double_from_seed (int seed) 02633 { 02634 return SAMPLE_INT32 * (double) seed + 0.3; 02635 } 02636 02637 static dbus_bool_t 02638 double_write_value (TestTypeNode *node, 02639 DataBlock *block, 02640 DBusTypeWriter *writer, 02641 int seed) 02642 { 02643 double v; 02644 02645 v = double_from_seed (seed); 02646 02647 return _dbus_type_writer_write_basic (writer, 02648 node->klass->typecode, 02649 &v); 02650 } 02651 02652 static dbus_bool_t 02653 double_read_value (TestTypeNode *node, 02654 DBusTypeReader *reader, 02655 int seed) 02656 { 02657 double v; 02658 double expected; 02659 02660 check_expected_type (reader, node->klass->typecode); 02661 02662 _dbus_type_reader_read_basic (reader, 02663 (double*) &v); 02664 02665 expected = double_from_seed (seed); 02666 02667 if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected)) 02668 { 02669 #ifdef DBUS_INT64_PRINTF_MODIFIER 02670 _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", 02671 expected, v, 02672 *(dbus_uint64_t*)(char*)&expected, 02673 *(dbus_uint64_t*)(char*)&v); 02674 #endif 02675 _dbus_assert_not_reached ("test failed"); 02676 } 02677 02678 return TRUE; 02679 } 02680 02681 static dbus_bool_t 02682 double_set_value (TestTypeNode *node, 02683 DBusTypeReader *reader, 02684 DBusTypeReader *realign_root, 02685 int seed) 02686 { 02687 double v; 02688 02689 v = double_from_seed (seed); 02690 02691 return _dbus_type_reader_set_basic (reader, 02692 &v, 02693 realign_root); 02694 } 02695 02696 #define MAX_SAMPLE_OBJECT_PATH_LEN 10 02697 static void 02698 object_path_from_seed (char *buf, 02699 int seed) 02700 { 02701 int i; 02702 unsigned char v; 02703 int len; 02704 02705 len = seed % 9; 02706 _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN); 02707 02708 v = (unsigned char) ('A' + seed); 02709 02710 if (len < 2) 02711 { 02712 buf[0] = '/'; 02713 i = 1; 02714 } 02715 else 02716 { 02717 i = 0; 02718 while (i + 1 < len) 02719 { 02720 if (v < 'A' || v > 'z') 02721 v = 'A'; 02722 02723 buf[i] = '/'; 02724 ++i; 02725 buf[i] = v; 02726 ++i; 02727 02728 v += 1; 02729 } 02730 } 02731 02732 buf[i] = '\0'; 02733 } 02734 02735 static dbus_bool_t 02736 object_path_write_value (TestTypeNode *node, 02737 DataBlock *block, 02738 DBusTypeWriter *writer, 02739 int seed) 02740 { 02741 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 02742 const char *v_string = buf; 02743 02744 object_path_from_seed (buf, seed); 02745 02746 return _dbus_type_writer_write_basic (writer, 02747 node->klass->typecode, 02748 &v_string); 02749 } 02750 02751 static dbus_bool_t 02752 object_path_read_value (TestTypeNode *node, 02753 DBusTypeReader *reader, 02754 int seed) 02755 { 02756 const char *v; 02757 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 02758 02759 check_expected_type (reader, node->klass->typecode); 02760 02761 _dbus_type_reader_read_basic (reader, 02762 (const char **) &v); 02763 02764 object_path_from_seed (buf, seed); 02765 02766 if (strcmp (buf, v) != 0) 02767 { 02768 _dbus_warn ("read object path '%s' expected '%s'\n", 02769 v, buf); 02770 _dbus_assert_not_reached ("test failed"); 02771 } 02772 02773 return TRUE; 02774 } 02775 02776 static dbus_bool_t 02777 object_path_set_value (TestTypeNode *node, 02778 DBusTypeReader *reader, 02779 DBusTypeReader *realign_root, 02780 int seed) 02781 { 02782 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 02783 const char *v_string = buf; 02784 02785 object_path_from_seed (buf, seed); 02786 02787 return _dbus_type_reader_set_basic (reader, 02788 &v_string, 02789 realign_root); 02790 } 02791 02792 #define MAX_SAMPLE_SIGNATURE_LEN 10 02793 static void 02794 signature_from_seed (char *buf, 02795 int seed) 02796 { 02797 /* try to avoid ascending, descending, or alternating length to help find bugs */ 02798 const char *sample_signatures[] = { 02799 "asax" 02800 "", 02801 "asau(xxxx)", 02802 "x", 02803 "ai", 02804 "a(ii)" 02805 }; 02806 02807 strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]); 02808 } 02809 02810 static dbus_bool_t 02811 signature_write_value (TestTypeNode *node, 02812 DataBlock *block, 02813 DBusTypeWriter *writer, 02814 int seed) 02815 { 02816 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 02817 const char *v_string = buf; 02818 02819 signature_from_seed (buf, seed); 02820 02821 return _dbus_type_writer_write_basic (writer, 02822 node->klass->typecode, 02823 &v_string); 02824 } 02825 02826 static dbus_bool_t 02827 signature_read_value (TestTypeNode *node, 02828 DBusTypeReader *reader, 02829 int seed) 02830 { 02831 const char *v; 02832 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 02833 02834 check_expected_type (reader, node->klass->typecode); 02835 02836 _dbus_type_reader_read_basic (reader, 02837 (const char **) &v); 02838 02839 signature_from_seed (buf, seed); 02840 02841 if (strcmp (buf, v) != 0) 02842 { 02843 _dbus_warn ("read signature value '%s' expected '%s'\n", 02844 v, buf); 02845 _dbus_assert_not_reached ("test failed"); 02846 } 02847 02848 return TRUE; 02849 } 02850 02851 02852 static dbus_bool_t 02853 signature_set_value (TestTypeNode *node, 02854 DBusTypeReader *reader, 02855 DBusTypeReader *realign_root, 02856 int seed) 02857 { 02858 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 02859 const char *v_string = buf; 02860 02861 signature_from_seed (buf, seed); 02862 02863 return _dbus_type_reader_set_basic (reader, 02864 &v_string, 02865 realign_root); 02866 } 02867 02868 static dbus_bool_t 02869 struct_write_value (TestTypeNode *node, 02870 DataBlock *block, 02871 DBusTypeWriter *writer, 02872 int seed) 02873 { 02874 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 02875 DataBlockState saved; 02876 DBusTypeWriter sub; 02877 int i; 02878 int n_copies; 02879 02880 n_copies = node->klass->subclass_detail; 02881 02882 _dbus_assert (container->children != NULL); 02883 02884 data_block_save (block, &saved); 02885 02886 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT, 02887 NULL, 0, 02888 &sub)) 02889 return FALSE; 02890 02891 i = 0; 02892 while (i < n_copies) 02893 { 02894 DBusList *link; 02895 02896 link = _dbus_list_get_first_link (&container->children); 02897 while (link != NULL) 02898 { 02899 TestTypeNode *child = link->data; 02900 DBusList *next = _dbus_list_get_next_link (&container->children, link); 02901 02902 if (!node_write_value (child, block, &sub, seed + i)) 02903 { 02904 data_block_restore (block, &saved); 02905 return FALSE; 02906 } 02907 02908 link = next; 02909 } 02910 02911 ++i; 02912 } 02913 02914 if (!_dbus_type_writer_unrecurse (writer, &sub)) 02915 { 02916 data_block_restore (block, &saved); 02917 return FALSE; 02918 } 02919 02920 return TRUE; 02921 } 02922 02923 static dbus_bool_t 02924 struct_read_or_set_value (TestTypeNode *node, 02925 DBusTypeReader *reader, 02926 DBusTypeReader *realign_root, 02927 int seed) 02928 { 02929 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 02930 DBusTypeReader sub; 02931 int i; 02932 int n_copies; 02933 02934 n_copies = node->klass->subclass_detail; 02935 02936 check_expected_type (reader, DBUS_TYPE_STRUCT); 02937 02938 _dbus_type_reader_recurse (reader, &sub); 02939 02940 i = 0; 02941 while (i < n_copies) 02942 { 02943 DBusList *link; 02944 02945 link = _dbus_list_get_first_link (&container->children); 02946 while (link != NULL) 02947 { 02948 TestTypeNode *child = link->data; 02949 DBusList *next = _dbus_list_get_next_link (&container->children, link); 02950 02951 if (realign_root == NULL) 02952 { 02953 if (!node_read_value (child, &sub, seed + i)) 02954 return FALSE; 02955 } 02956 else 02957 { 02958 if (!node_set_value (child, &sub, realign_root, seed + i)) 02959 return FALSE; 02960 } 02961 02962 if (i == (n_copies - 1) && next == NULL) 02963 NEXT_EXPECTING_FALSE (&sub); 02964 else 02965 NEXT_EXPECTING_TRUE (&sub); 02966 02967 link = next; 02968 } 02969 02970 ++i; 02971 } 02972 02973 return TRUE; 02974 } 02975 02976 static dbus_bool_t 02977 struct_read_value (TestTypeNode *node, 02978 DBusTypeReader *reader, 02979 int seed) 02980 { 02981 return struct_read_or_set_value (node, reader, NULL, seed); 02982 } 02983 02984 static dbus_bool_t 02985 struct_set_value (TestTypeNode *node, 02986 DBusTypeReader *reader, 02987 DBusTypeReader *realign_root, 02988 int seed) 02989 { 02990 return struct_read_or_set_value (node, reader, realign_root, seed); 02991 } 02992 02993 static dbus_bool_t 02994 struct_build_signature (TestTypeNode *node, 02995 DBusString *str) 02996 { 02997 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 02998 int i; 02999 int orig_len; 03000 int n_copies; 03001 03002 n_copies = node->klass->subclass_detail; 03003 03004 orig_len = _dbus_string_get_length (str); 03005 03006 if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR)) 03007 goto oom; 03008 03009 i = 0; 03010 while (i < n_copies) 03011 { 03012 DBusList *link; 03013 03014 link = _dbus_list_get_first_link (&container->children); 03015 while (link != NULL) 03016 { 03017 TestTypeNode *child = link->data; 03018 DBusList *next = _dbus_list_get_next_link (&container->children, link); 03019 03020 if (!node_build_signature (child, str)) 03021 goto oom; 03022 03023 link = next; 03024 } 03025 03026 ++i; 03027 } 03028 03029 if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR)) 03030 goto oom; 03031 03032 return TRUE; 03033 03034 oom: 03035 _dbus_string_set_length (str, orig_len); 03036 return FALSE; 03037 } 03038 03039 static dbus_bool_t 03040 array_write_value (TestTypeNode *node, 03041 DataBlock *block, 03042 DBusTypeWriter *writer, 03043 int seed) 03044 { 03045 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03046 DataBlockState saved; 03047 DBusTypeWriter sub; 03048 DBusString element_signature; 03049 int i; 03050 int n_copies; 03051 int element_type; 03052 TestTypeNode *child; 03053 03054 n_copies = node->klass->subclass_detail; 03055 03056 _dbus_assert (container->children != NULL); 03057 03058 data_block_save (block, &saved); 03059 03060 if (!_dbus_string_init (&element_signature)) 03061 return FALSE; 03062 03063 child = _dbus_list_get_first (&container->children); 03064 03065 if (!node_build_signature (child, 03066 &element_signature)) 03067 goto oom; 03068 03069 element_type = _dbus_first_type_in_signature (&element_signature, 0); 03070 03071 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, 03072 &element_signature, 0, 03073 &sub)) 03074 goto oom; 03075 03076 if (arrays_write_fixed_in_blocks && 03077 dbus_type_is_fixed (element_type) && 03078 child->klass->write_multi) 03079 { 03080 if (!node_write_multi (child, block, &sub, seed, n_copies)) 03081 goto oom; 03082 } 03083 else 03084 { 03085 i = 0; 03086 while (i < n_copies) 03087 { 03088 DBusList *link; 03089 03090 link = _dbus_list_get_first_link (&container->children); 03091 while (link != NULL) 03092 { 03093 TestTypeNode *child = link->data; 03094 DBusList *next = _dbus_list_get_next_link (&container->children, link); 03095 03096 if (!node_write_value (child, block, &sub, seed + i)) 03097 goto oom; 03098 03099 link = next; 03100 } 03101 03102 ++i; 03103 } 03104 } 03105 03106 if (!_dbus_type_writer_unrecurse (writer, &sub)) 03107 goto oom; 03108 03109 _dbus_string_free (&element_signature); 03110 return TRUE; 03111 03112 oom: 03113 data_block_restore (block, &saved); 03114 _dbus_string_free (&element_signature); 03115 return FALSE; 03116 } 03117 03118 static dbus_bool_t 03119 array_read_or_set_value (TestTypeNode *node, 03120 DBusTypeReader *reader, 03121 DBusTypeReader *realign_root, 03122 int seed) 03123 { 03124 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03125 DBusTypeReader sub; 03126 int i; 03127 int n_copies; 03128 TestTypeNode *child; 03129 03130 n_copies = node->klass->subclass_detail; 03131 03132 check_expected_type (reader, DBUS_TYPE_ARRAY); 03133 03134 child = _dbus_list_get_first (&container->children); 03135 03136 if (n_copies > 0) 03137 { 03138 _dbus_type_reader_recurse (reader, &sub); 03139 03140 if (realign_root == NULL && arrays_write_fixed_in_blocks && 03141 dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) && 03142 child->klass->read_multi) 03143 { 03144 if (!node_read_multi (child, &sub, seed, n_copies)) 03145 return FALSE; 03146 } 03147 else 03148 { 03149 i = 0; 03150 while (i < n_copies) 03151 { 03152 DBusList *link; 03153 03154 link = _dbus_list_get_first_link (&container->children); 03155 while (link != NULL) 03156 { 03157 TestTypeNode *child = link->data; 03158 DBusList *next = _dbus_list_get_next_link (&container->children, link); 03159 03160 _dbus_assert (child->klass->typecode == 03161 _dbus_type_reader_get_element_type (reader)); 03162 03163 if (realign_root == NULL) 03164 { 03165 if (!node_read_value (child, &sub, seed + i)) 03166 return FALSE; 03167 } 03168 else 03169 { 03170 if (!node_set_value (child, &sub, realign_root, seed + i)) 03171 return FALSE; 03172 } 03173 03174 if (i == (n_copies - 1) && next == NULL) 03175 NEXT_EXPECTING_FALSE (&sub); 03176 else 03177 NEXT_EXPECTING_TRUE (&sub); 03178 03179 link = next; 03180 } 03181 03182 ++i; 03183 } 03184 } 03185 } 03186 03187 return TRUE; 03188 } 03189 03190 static dbus_bool_t 03191 array_read_value (TestTypeNode *node, 03192 DBusTypeReader *reader, 03193 int seed) 03194 { 03195 return array_read_or_set_value (node, reader, NULL, seed); 03196 } 03197 03198 static dbus_bool_t 03199 array_set_value (TestTypeNode *node, 03200 DBusTypeReader *reader, 03201 DBusTypeReader *realign_root, 03202 int seed) 03203 { 03204 return array_read_or_set_value (node, reader, realign_root, seed); 03205 } 03206 03207 static dbus_bool_t 03208 array_build_signature (TestTypeNode *node, 03209 DBusString *str) 03210 { 03211 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03212 int orig_len; 03213 03214 orig_len = _dbus_string_get_length (str); 03215 03216 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) 03217 goto oom; 03218 03219 if (!node_build_signature (_dbus_list_get_first (&container->children), 03220 str)) 03221 goto oom; 03222 03223 return TRUE; 03224 03225 oom: 03226 _dbus_string_set_length (str, orig_len); 03227 return FALSE; 03228 } 03229 03230 /* 10 is random just to add another seed that we use in the suite */ 03231 #define VARIANT_SEED 10 03232 03233 static dbus_bool_t 03234 variant_write_value (TestTypeNode *node, 03235 DataBlock *block, 03236 DBusTypeWriter *writer, 03237 int seed) 03238 { 03239 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03240 DataBlockState saved; 03241 DBusTypeWriter sub; 03242 DBusString content_signature; 03243 TestTypeNode *child; 03244 03245 _dbus_assert (container->children != NULL); 03246 _dbus_assert (_dbus_list_length_is_one (&container->children)); 03247 03248 child = _dbus_list_get_first (&container->children); 03249 03250 data_block_save (block, &saved); 03251 03252 if (!_dbus_string_init (&content_signature)) 03253 return FALSE; 03254 03255 if (!node_build_signature (child, 03256 &content_signature)) 03257 goto oom; 03258 03259 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT, 03260 &content_signature, 0, 03261 &sub)) 03262 goto oom; 03263 03264 if (!node_write_value (child, block, &sub, seed + VARIANT_SEED)) 03265 goto oom; 03266 03267 if (!_dbus_type_writer_unrecurse (writer, &sub)) 03268 goto oom; 03269 03270 _dbus_string_free (&content_signature); 03271 return TRUE; 03272 03273 oom: 03274 data_block_restore (block, &saved); 03275 _dbus_string_free (&content_signature); 03276 return FALSE; 03277 } 03278 03279 static dbus_bool_t 03280 variant_read_or_set_value (TestTypeNode *node, 03281 DBusTypeReader *reader, 03282 DBusTypeReader *realign_root, 03283 int seed) 03284 { 03285 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03286 DBusTypeReader sub; 03287 TestTypeNode *child; 03288 03289 _dbus_assert (container->children != NULL); 03290 _dbus_assert (_dbus_list_length_is_one (&container->children)); 03291 03292 child = _dbus_list_get_first (&container->children); 03293 03294 check_expected_type (reader, DBUS_TYPE_VARIANT); 03295 03296 _dbus_type_reader_recurse (reader, &sub); 03297 03298 if (realign_root == NULL) 03299 { 03300 if (!node_read_value (child, &sub, seed + VARIANT_SEED)) 03301 return FALSE; 03302 } 03303 else 03304 { 03305 if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED)) 03306 return FALSE; 03307 } 03308 03309 NEXT_EXPECTING_FALSE (&sub); 03310 03311 return TRUE; 03312 } 03313 03314 static dbus_bool_t 03315 variant_read_value (TestTypeNode *node, 03316 DBusTypeReader *reader, 03317 int seed) 03318 { 03319 return variant_read_or_set_value (node, reader, NULL, seed); 03320 } 03321 03322 static dbus_bool_t 03323 variant_set_value (TestTypeNode *node, 03324 DBusTypeReader *reader, 03325 DBusTypeReader *realign_root, 03326 int seed) 03327 { 03328 return variant_read_or_set_value (node, reader, realign_root, seed); 03329 } 03330 03331 static dbus_bool_t 03332 dict_write_value (TestTypeNode *node, 03333 DataBlock *block, 03334 DBusTypeWriter *writer, 03335 int seed) 03336 { 03337 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03338 DataBlockState saved; 03339 DBusTypeWriter sub; 03340 DBusString entry_value_signature; 03341 DBusString dict_entry_signature; 03342 int i; 03343 int n_entries; 03344 TestTypeNode *child; 03345 03346 n_entries = node->klass->subclass_detail; 03347 03348 _dbus_assert (container->children != NULL); 03349 03350 data_block_save (block, &saved); 03351 03352 if (!_dbus_string_init (&entry_value_signature)) 03353 return FALSE; 03354 03355 if (!_dbus_string_init (&dict_entry_signature)) 03356 { 03357 _dbus_string_free (&entry_value_signature); 03358 return FALSE; 03359 } 03360 03361 child = _dbus_list_get_first (&container->children); 03362 03363 if (!node_build_signature (child, 03364 &entry_value_signature)) 03365 goto oom; 03366 03367 if (!_dbus_string_append (&dict_entry_signature, 03368 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 03369 DBUS_TYPE_INT32_AS_STRING)) 03370 goto oom; 03371 03372 if (!_dbus_string_copy (&entry_value_signature, 0, 03373 &dict_entry_signature, 03374 _dbus_string_get_length (&dict_entry_signature))) 03375 goto oom; 03376 03377 if (!_dbus_string_append_byte (&dict_entry_signature, 03378 DBUS_DICT_ENTRY_END_CHAR)) 03379 goto oom; 03380 03381 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, 03382 &dict_entry_signature, 0, 03383 &sub)) 03384 goto oom; 03385 03386 i = 0; 03387 while (i < n_entries) 03388 { 03389 DBusTypeWriter entry_sub; 03390 dbus_int32_t key; 03391 03392 if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY, 03393 NULL, 0, 03394 &entry_sub)) 03395 goto oom; 03396 03397 key = int32_from_seed (seed + i); 03398 03399 if (!_dbus_type_writer_write_basic (&entry_sub, 03400 DBUS_TYPE_INT32, 03401 &key)) 03402 goto oom; 03403 03404 if (!node_write_value (child, block, &entry_sub, seed + i)) 03405 goto oom; 03406 03407 if (!_dbus_type_writer_unrecurse (&sub, &entry_sub)) 03408 goto oom; 03409 03410 ++i; 03411 } 03412 03413 if (!_dbus_type_writer_unrecurse (writer, &sub)) 03414 goto oom; 03415 03416 _dbus_string_free (&entry_value_signature); 03417 _dbus_string_free (&dict_entry_signature); 03418 return TRUE; 03419 03420 oom: 03421 data_block_restore (block, &saved); 03422 _dbus_string_free (&entry_value_signature); 03423 _dbus_string_free (&dict_entry_signature); 03424 return FALSE; 03425 } 03426 03427 static dbus_bool_t 03428 dict_read_or_set_value (TestTypeNode *node, 03429 DBusTypeReader *reader, 03430 DBusTypeReader *realign_root, 03431 int seed) 03432 { 03433 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03434 DBusTypeReader sub; 03435 int i; 03436 int n_entries; 03437 TestTypeNode *child; 03438 03439 n_entries = node->klass->subclass_detail; 03440 03441 check_expected_type (reader, DBUS_TYPE_ARRAY); 03442 03443 child = _dbus_list_get_first (&container->children); 03444 03445 if (n_entries > 0) 03446 { 03447 _dbus_type_reader_recurse (reader, &sub); 03448 03449 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); 03450 03451 i = 0; 03452 while (i < n_entries) 03453 { 03454 DBusTypeReader entry_sub; 03455 03456 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); 03457 03458 _dbus_type_reader_recurse (&sub, &entry_sub); 03459 03460 if (realign_root == NULL) 03461 { 03462 dbus_int32_t v; 03463 03464 check_expected_type (&entry_sub, DBUS_TYPE_INT32); 03465 03466 _dbus_type_reader_read_basic (&entry_sub, 03467 (dbus_int32_t*) &v); 03468 03469 _dbus_assert (v == int32_from_seed (seed + i)); 03470 03471 NEXT_EXPECTING_TRUE (&entry_sub); 03472 03473 if (!node_read_value (child, &entry_sub, seed + i)) 03474 return FALSE; 03475 03476 NEXT_EXPECTING_FALSE (&entry_sub); 03477 } 03478 else 03479 { 03480 dbus_int32_t v; 03481 03482 v = int32_from_seed (seed + i); 03483 03484 if (!_dbus_type_reader_set_basic (&entry_sub, 03485 &v, 03486 realign_root)) 03487 return FALSE; 03488 03489 NEXT_EXPECTING_TRUE (&entry_sub); 03490 03491 if (!node_set_value (child, &entry_sub, realign_root, seed + i)) 03492 return FALSE; 03493 03494 NEXT_EXPECTING_FALSE (&entry_sub); 03495 } 03496 03497 if (i == (n_entries - 1)) 03498 NEXT_EXPECTING_FALSE (&sub); 03499 else 03500 NEXT_EXPECTING_TRUE (&sub); 03501 03502 ++i; 03503 } 03504 } 03505 03506 return TRUE; 03507 } 03508 03509 static dbus_bool_t 03510 dict_read_value (TestTypeNode *node, 03511 DBusTypeReader *reader, 03512 int seed) 03513 { 03514 return dict_read_or_set_value (node, reader, NULL, seed); 03515 } 03516 03517 static dbus_bool_t 03518 dict_set_value (TestTypeNode *node, 03519 DBusTypeReader *reader, 03520 DBusTypeReader *realign_root, 03521 int seed) 03522 { 03523 return dict_read_or_set_value (node, reader, realign_root, seed); 03524 } 03525 03526 static dbus_bool_t 03527 dict_build_signature (TestTypeNode *node, 03528 DBusString *str) 03529 { 03530 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03531 int orig_len; 03532 03533 orig_len = _dbus_string_get_length (str); 03534 03535 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) 03536 goto oom; 03537 03538 if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING)) 03539 goto oom; 03540 03541 if (!node_build_signature (_dbus_list_get_first (&container->children), 03542 str)) 03543 goto oom; 03544 03545 if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR)) 03546 goto oom; 03547 03548 return TRUE; 03549 03550 oom: 03551 _dbus_string_set_length (str, orig_len); 03552 return FALSE; 03553 } 03554 03555 static void 03556 container_destroy (TestTypeNode *node) 03557 { 03558 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 03559 DBusList *link; 03560 03561 link = _dbus_list_get_first_link (&container->children); 03562 while (link != NULL) 03563 { 03564 TestTypeNode *child = link->data; 03565 DBusList *next = _dbus_list_get_next_link (&container->children, link); 03566 03567 node_destroy (child); 03568 03569 _dbus_list_free_link (link); 03570 03571 link = next; 03572 } 03573 } 03574 03575 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 03576 03577 #endif /* DBUS_BUILD_TESTS */