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