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