1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-marshal-recursive-util.c Would be in dbus-marshal-recursive.c, but only used in bus/tests 3 * 4 * Copyright (C) 2004, 2005 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 26 #ifdef DBUS_BUILD_TESTS 27 28 #include "dbus-marshal-recursive.h" 29 #include "dbus-marshal-basic.h" 30 #include "dbus-signature.h" 31 #include "dbus-internals.h" 32 #include <string.h> 33 34 static void 35 basic_value_zero (DBusBasicValue *value) 36 { 37 38 #ifdef DBUS_HAVE_INT64 39 value->u64 = 0; 40 #else 41 value->u64.first32 = 0; 42 value->u64.second32 = 0; 43 #endif 44 } 45 46 static dbus_bool_t 47 basic_value_equal (int type, 48 DBusBasicValue *lhs, 49 DBusBasicValue *rhs) 50 { 51 if (type == DBUS_TYPE_STRING || 52 type == DBUS_TYPE_SIGNATURE || 53 type == DBUS_TYPE_OBJECT_PATH) 54 { 55 return strcmp (lhs->str, rhs->str) == 0; 56 } 57 else 58 { 59 #ifdef DBUS_HAVE_INT64 60 return lhs->u64 == rhs->u64; 61 #else 62 return lhs->u64.first32 == rhs->u64.first32 && 63 lhs->u64.second32 == rhs->u64.second32; 64 #endif 65 } 66 } 67 68 static dbus_bool_t 69 equal_values_helper (DBusTypeReader *lhs, 70 DBusTypeReader *rhs) 71 { 72 int lhs_type; 73 int rhs_type; 74 75 lhs_type = _dbus_type_reader_get_current_type (lhs); 76 rhs_type = _dbus_type_reader_get_current_type (rhs); 77 78 if (lhs_type != rhs_type) 79 return FALSE; 80 81 if (lhs_type == DBUS_TYPE_INVALID) 82 return TRUE; 83 84 if (dbus_type_is_basic (lhs_type)) 85 { 86 DBusBasicValue lhs_value; 87 DBusBasicValue rhs_value; 88 89 basic_value_zero (&lhs_value); 90 basic_value_zero (&rhs_value); 91 92 _dbus_type_reader_read_basic (lhs, &lhs_value); 93 _dbus_type_reader_read_basic (rhs, &rhs_value); 94 95 return basic_value_equal (lhs_type, &lhs_value, &rhs_value); 96 } 97 else 98 { 99 DBusTypeReader lhs_sub; 100 DBusTypeReader rhs_sub; 101 102 _dbus_type_reader_recurse (lhs, &lhs_sub); 103 _dbus_type_reader_recurse (rhs, &rhs_sub); 104 105 return equal_values_helper (&lhs_sub, &rhs_sub); 106 } 107 } 108 109 /** 110 * See whether the two readers point to identical data blocks. 111 * 112 * @param lhs reader 1 113 * @param rhs reader 2 114 * @returns #TRUE if the data blocks have the same values 115 */ 116 dbus_bool_t 117 _dbus_type_reader_equal_values (const DBusTypeReader *lhs, 118 const DBusTypeReader *rhs) 119 { 120 DBusTypeReader copy_lhs = *lhs; 121 DBusTypeReader copy_rhs = *rhs; 122 123 return equal_values_helper (©_lhs, ©_rhs); 124 } 125 126 /* TESTS */ 127 128 #ifndef DOXYGEN_SHOULD_SKIP_THIS 129 130 #include "dbus-test.h" 131 #include "dbus-list.h" 132 #include <stdio.h> 133 #include <stdlib.h> 134 135 /* Whether to do the OOM stuff (only with other expensive tests) */ 136 #define TEST_OOM_HANDLING 0 137 /* We do start offset 0 through 9, to get various alignment cases. Still this 138 * obviously makes the test suite run 10x as slow. 139 */ 140 #define MAX_INITIAL_OFFSET 9 141 142 /* Largest iteration count to test copying, realignment, 143 * etc. with. i.e. we only test this stuff with some of the smaller 144 * data sets. 145 */ 146 #define MAX_ITERATIONS_FOR_EXPENSIVE_TESTS 1000 147 148 typedef struct 149 { 150 int byte_order; 151 int initial_offset; 152 DBusString signature; 153 DBusString body; 154 } DataBlock; 155 156 typedef struct 157 { 158 int saved_sig_len; 159 int saved_body_len; 160 } DataBlockState; 161 162 #define N_FENCE_BYTES 5 163 #define FENCE_BYTES_STR "abcde" 164 #define INITIAL_PADDING_BYTE '\0' 165 166 static dbus_bool_t 167 data_block_init (DataBlock *block, 168 int byte_order, 169 int initial_offset) 170 { 171 if (!_dbus_string_init (&block->signature)) 172 return FALSE; 173 174 if (!_dbus_string_init (&block->body)) 175 { 176 _dbus_string_free (&block->signature); 177 return FALSE; 178 } 179 180 if (!_dbus_string_insert_bytes (&block->signature, 0, initial_offset, 181 INITIAL_PADDING_BYTE) || 182 !_dbus_string_insert_bytes (&block->body, 0, initial_offset, 183 INITIAL_PADDING_BYTE) || 184 !_dbus_string_append (&block->signature, FENCE_BYTES_STR) || 185 !_dbus_string_append (&block->body, FENCE_BYTES_STR)) 186 { 187 _dbus_string_free (&block->signature); 188 _dbus_string_free (&block->body); 189 return FALSE; 190 } 191 192 block->byte_order = byte_order; 193 block->initial_offset = initial_offset; 194 195 return TRUE; 196 } 197 198 static void 199 data_block_save (DataBlock *block, 200 DataBlockState *state) 201 { 202 state->saved_sig_len = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES; 203 state->saved_body_len = _dbus_string_get_length (&block->body) - N_FENCE_BYTES; 204 } 205 206 static void 207 data_block_restore (DataBlock *block, 208 DataBlockState *state) 209 { 210 _dbus_string_delete (&block->signature, 211 state->saved_sig_len, 212 _dbus_string_get_length (&block->signature) - state->saved_sig_len - N_FENCE_BYTES); 213 _dbus_string_delete (&block->body, 214 state->saved_body_len, 215 _dbus_string_get_length (&block->body) - state->saved_body_len - N_FENCE_BYTES); 216 } 217 218 static void 219 data_block_verify (DataBlock *block) 220 { 221 if (!_dbus_string_ends_with_c_str (&block->signature, 222 FENCE_BYTES_STR)) 223 { 224 int offset; 225 226 offset = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - 8; 227 if (offset < 0) 228 offset = 0; 229 230 _dbus_verbose_bytes_of_string (&block->signature, 231 offset, 232 _dbus_string_get_length (&block->signature) - offset); 233 _dbus_assert_not_reached ("block did not verify: bad bytes at end of signature"); 234 } 235 if (!_dbus_string_ends_with_c_str (&block->body, 236 FENCE_BYTES_STR)) 237 { 238 int offset; 239 240 offset = _dbus_string_get_length (&block->body) - N_FENCE_BYTES - 8; 241 if (offset < 0) 242 offset = 0; 243 244 _dbus_verbose_bytes_of_string (&block->body, 245 offset, 246 _dbus_string_get_length (&block->body) - offset); 247 _dbus_assert_not_reached ("block did not verify: bad bytes at end of body"); 248 } 249 250 _dbus_assert (_dbus_string_validate_nul (&block->signature, 251 0, block->initial_offset)); 252 _dbus_assert (_dbus_string_validate_nul (&block->body, 253 0, block->initial_offset)); 254 } 255 256 static void 257 data_block_free (DataBlock *block) 258 { 259 data_block_verify (block); 260 261 _dbus_string_free (&block->signature); 262 _dbus_string_free (&block->body); 263 } 264 265 static void 266 data_block_reset (DataBlock *block) 267 { 268 data_block_verify (block); 269 270 _dbus_string_delete (&block->signature, 271 block->initial_offset, 272 _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - block->initial_offset); 273 _dbus_string_delete (&block->body, 274 block->initial_offset, 275 _dbus_string_get_length (&block->body) - N_FENCE_BYTES - block->initial_offset); 276 277 data_block_verify (block); 278 } 279 280 static void 281 data_block_init_reader_writer (DataBlock *block, 282 DBusTypeReader *reader, 283 DBusTypeWriter *writer) 284 { 285 if (reader) 286 _dbus_type_reader_init (reader, 287 block->byte_order, 288 &block->signature, 289 block->initial_offset, 290 &block->body, 291 block->initial_offset); 292 293 if (writer) 294 _dbus_type_writer_init (writer, 295 block->byte_order, 296 &block->signature, 297 _dbus_string_get_length (&block->signature) - N_FENCE_BYTES, 298 &block->body, 299 _dbus_string_get_length (&block->body) - N_FENCE_BYTES); 300 } 301 302 static void 303 real_check_expected_type (DBusTypeReader *reader, 304 int expected, 305 const char *funcname, 306 int line) 307 { 308 int t; 309 310 t = _dbus_type_reader_get_current_type (reader); 311 312 if (t != expected) 313 { 314 _dbus_warn ("Read type %s while expecting %s at %s line %d\n", 315 _dbus_type_to_string (t), 316 _dbus_type_to_string (expected), 317 funcname, line); 318 319 _dbus_assert_not_reached ("read wrong type"); 320 } 321 } 322 323 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__) 324 325 #define NEXT_EXPECTING_TRUE(reader) do { if (!_dbus_type_reader_next (reader)) \ 326 { \ 327 _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n", \ 328 _DBUS_FUNCTION_NAME, __LINE__); \ 329 _dbus_assert_not_reached ("test failed"); \ 330 } \ 331 } while (0) 332 333 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader)) \ 334 { \ 335 _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n", \ 336 _DBUS_FUNCTION_NAME, __LINE__); \ 337 _dbus_assert_not_reached ("test failed"); \ 338 } \ 339 check_expected_type (reader, DBUS_TYPE_INVALID); \ 340 } while (0) 341 342 typedef struct TestTypeNode TestTypeNode; 343 typedef struct TestTypeNodeClass TestTypeNodeClass; 344 typedef struct TestTypeNodeContainer TestTypeNodeContainer; 345 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass; 346 347 struct TestTypeNode 348 { 349 const TestTypeNodeClass *klass; 350 }; 351 352 struct TestTypeNodeContainer 353 { 354 TestTypeNode base; 355 DBusList *children; 356 }; 357 358 struct TestTypeNodeClass 359 { 360 int typecode; 361 362 int instance_size; 363 364 int subclass_detail; /* a bad hack to avoid a bunch of subclass casting */ 365 366 dbus_bool_t (* construct) (TestTypeNode *node); 367 void (* destroy) (TestTypeNode *node); 368 369 dbus_bool_t (* write_value) (TestTypeNode *node, 370 DataBlock *block, 371 DBusTypeWriter *writer, 372 int seed); 373 dbus_bool_t (* read_value) (TestTypeNode *node, 374 DBusTypeReader *reader, 375 int seed); 376 dbus_bool_t (* set_value) (TestTypeNode *node, 377 DBusTypeReader *reader, 378 DBusTypeReader *realign_root, 379 int seed); 380 dbus_bool_t (* build_signature) (TestTypeNode *node, 381 DBusString *str); 382 dbus_bool_t (* write_multi) (TestTypeNode *node, 383 DataBlock *block, 384 DBusTypeWriter *writer, 385 int seed, 386 int count); 387 dbus_bool_t (* read_multi) (TestTypeNode *node, 388 DBusTypeReader *reader, 389 int seed, 390 int count); 391 }; 392 393 struct TestTypeNodeContainerClass 394 { 395 TestTypeNodeClass base; 396 }; 397 398 /* FIXME this could be chilled out substantially by unifying 399 * the basic types into basic_write_value/basic_read_value 400 * and by merging read_value and set_value into one function 401 * taking a flag argument. 402 */ 403 static dbus_bool_t int16_write_value (TestTypeNode *node, 404 DataBlock *block, 405 DBusTypeWriter *writer, 406 int seed); 407 static dbus_bool_t int16_read_value (TestTypeNode *node, 408 DBusTypeReader *reader, 409 int seed); 410 static dbus_bool_t int16_set_value (TestTypeNode *node, 411 DBusTypeReader *reader, 412 DBusTypeReader *realign_root, 413 int seed); 414 static dbus_bool_t int16_write_multi (TestTypeNode *node, 415 DataBlock *block, 416 DBusTypeWriter *writer, 417 int seed, 418 int count); 419 static dbus_bool_t int16_read_multi (TestTypeNode *node, 420 DBusTypeReader *reader, 421 int seed, 422 int count); 423 static dbus_bool_t int32_write_value (TestTypeNode *node, 424 DataBlock *block, 425 DBusTypeWriter *writer, 426 int seed); 427 static dbus_bool_t int32_read_value (TestTypeNode *node, 428 DBusTypeReader *reader, 429 int seed); 430 static dbus_bool_t int32_set_value (TestTypeNode *node, 431 DBusTypeReader *reader, 432 DBusTypeReader *realign_root, 433 int seed); 434 static dbus_bool_t int32_write_multi (TestTypeNode *node, 435 DataBlock *block, 436 DBusTypeWriter *writer, 437 int seed, 438 int count); 439 static dbus_bool_t int32_read_multi (TestTypeNode *node, 440 DBusTypeReader *reader, 441 int seed, 442 int count); 443 static dbus_bool_t int64_write_value (TestTypeNode *node, 444 DataBlock *block, 445 DBusTypeWriter *writer, 446 int seed); 447 static dbus_bool_t int64_read_value (TestTypeNode *node, 448 DBusTypeReader *reader, 449 int seed); 450 static dbus_bool_t int64_set_value (TestTypeNode *node, 451 DBusTypeReader *reader, 452 DBusTypeReader *realign_root, 453 int seed); 454 static dbus_bool_t string_write_value (TestTypeNode *node, 455 DataBlock *block, 456 DBusTypeWriter *writer, 457 int seed); 458 static dbus_bool_t string_read_value (TestTypeNode *node, 459 DBusTypeReader *reader, 460 int seed); 461 static dbus_bool_t string_set_value (TestTypeNode *node, 462 DBusTypeReader *reader, 463 DBusTypeReader *realign_root, 464 int seed); 465 static dbus_bool_t bool_write_value (TestTypeNode *node, 466 DataBlock *block, 467 DBusTypeWriter *writer, 468 int seed); 469 static dbus_bool_t bool_read_value (TestTypeNode *node, 470 DBusTypeReader *reader, 471 int seed); 472 static dbus_bool_t bool_set_value (TestTypeNode *node, 473 DBusTypeReader *reader, 474 DBusTypeReader *realign_root, 475 int seed); 476 static dbus_bool_t byte_write_value (TestTypeNode *node, 477 DataBlock *block, 478 DBusTypeWriter *writer, 479 int seed); 480 static dbus_bool_t byte_read_value (TestTypeNode *node, 481 DBusTypeReader *reader, 482 int seed); 483 static dbus_bool_t byte_set_value (TestTypeNode *node, 484 DBusTypeReader *reader, 485 DBusTypeReader *realign_root, 486 int seed); 487 static dbus_bool_t double_write_value (TestTypeNode *node, 488 DataBlock *block, 489 DBusTypeWriter *writer, 490 int seed); 491 static dbus_bool_t double_read_value (TestTypeNode *node, 492 DBusTypeReader *reader, 493 int seed); 494 static dbus_bool_t double_set_value (TestTypeNode *node, 495 DBusTypeReader *reader, 496 DBusTypeReader *realign_root, 497 int seed); 498 static dbus_bool_t object_path_write_value (TestTypeNode *node, 499 DataBlock *block, 500 DBusTypeWriter *writer, 501 int seed); 502 static dbus_bool_t object_path_read_value (TestTypeNode *node, 503 DBusTypeReader *reader, 504 int seed); 505 static dbus_bool_t object_path_set_value (TestTypeNode *node, 506 DBusTypeReader *reader, 507 DBusTypeReader *realign_root, 508 int seed); 509 static dbus_bool_t signature_write_value (TestTypeNode *node, 510 DataBlock *block, 511 DBusTypeWriter *writer, 512 int seed); 513 static dbus_bool_t signature_read_value (TestTypeNode *node, 514 DBusTypeReader *reader, 515 int seed); 516 static dbus_bool_t signature_set_value (TestTypeNode *node, 517 DBusTypeReader *reader, 518 DBusTypeReader *realign_root, 519 int seed); 520 static dbus_bool_t struct_write_value (TestTypeNode *node, 521 DataBlock *block, 522 DBusTypeWriter *writer, 523 int seed); 524 static dbus_bool_t struct_read_value (TestTypeNode *node, 525 DBusTypeReader *reader, 526 int seed); 527 static dbus_bool_t struct_set_value (TestTypeNode *node, 528 DBusTypeReader *reader, 529 DBusTypeReader *realign_root, 530 int seed); 531 static dbus_bool_t struct_build_signature (TestTypeNode *node, 532 DBusString *str); 533 static dbus_bool_t dict_write_value (TestTypeNode *node, 534 DataBlock *block, 535 DBusTypeWriter *writer, 536 int seed); 537 static dbus_bool_t dict_read_value (TestTypeNode *node, 538 DBusTypeReader *reader, 539 int seed); 540 static dbus_bool_t dict_set_value (TestTypeNode *node, 541 DBusTypeReader *reader, 542 DBusTypeReader *realign_root, 543 int seed); 544 static dbus_bool_t dict_build_signature (TestTypeNode *node, 545 DBusString *str); 546 static dbus_bool_t array_write_value (TestTypeNode *node, 547 DataBlock *block, 548 DBusTypeWriter *writer, 549 int seed); 550 static dbus_bool_t array_read_value (TestTypeNode *node, 551 DBusTypeReader *reader, 552 int seed); 553 static dbus_bool_t array_set_value (TestTypeNode *node, 554 DBusTypeReader *reader, 555 DBusTypeReader *realign_root, 556 int seed); 557 static dbus_bool_t array_build_signature (TestTypeNode *node, 558 DBusString *str); 559 static dbus_bool_t variant_write_value (TestTypeNode *node, 560 DataBlock *block, 561 DBusTypeWriter *writer, 562 int seed); 563 static dbus_bool_t variant_read_value (TestTypeNode *node, 564 DBusTypeReader *reader, 565 int seed); 566 static dbus_bool_t variant_set_value (TestTypeNode *node, 567 DBusTypeReader *reader, 568 DBusTypeReader *realign_root, 569 int seed); 570 static void container_destroy (TestTypeNode *node); 571 572 573 574 static const TestTypeNodeClass int16_class = { 575 DBUS_TYPE_INT16, 576 sizeof (TestTypeNode), 577 0, 578 NULL, 579 NULL, 580 int16_write_value, 581 int16_read_value, 582 int16_set_value, 583 NULL, 584 int16_write_multi, 585 int16_read_multi 586 }; 587 588 static const TestTypeNodeClass uint16_class = { 589 DBUS_TYPE_UINT16, 590 sizeof (TestTypeNode), 591 0, 592 NULL, 593 NULL, 594 int16_write_value, /* recycle from int16 */ 595 int16_read_value, /* recycle from int16 */ 596 int16_set_value, /* recycle from int16 */ 597 NULL, 598 int16_write_multi, /* recycle from int16 */ 599 int16_read_multi /* recycle from int16 */ 600 }; 601 602 static const TestTypeNodeClass int32_class = { 603 DBUS_TYPE_INT32, 604 sizeof (TestTypeNode), 605 0, 606 NULL, 607 NULL, 608 int32_write_value, 609 int32_read_value, 610 int32_set_value, 611 NULL, 612 int32_write_multi, 613 int32_read_multi 614 }; 615 616 static const TestTypeNodeClass uint32_class = { 617 DBUS_TYPE_UINT32, 618 sizeof (TestTypeNode), 619 0, 620 NULL, 621 NULL, 622 int32_write_value, /* recycle from int32 */ 623 int32_read_value, /* recycle from int32 */ 624 int32_set_value, /* recycle from int32 */ 625 NULL, 626 int32_write_multi, /* recycle from int32 */ 627 int32_read_multi /* recycle from int32 */ 628 }; 629 630 static const TestTypeNodeClass int64_class = { 631 DBUS_TYPE_INT64, 632 sizeof (TestTypeNode), 633 0, 634 NULL, 635 NULL, 636 int64_write_value, 637 int64_read_value, 638 int64_set_value, 639 NULL, 640 NULL, /* FIXME */ 641 NULL /* FIXME */ 642 }; 643 644 static const TestTypeNodeClass uint64_class = { 645 DBUS_TYPE_UINT64, 646 sizeof (TestTypeNode), 647 0, 648 NULL, 649 NULL, 650 int64_write_value, /* recycle from int64 */ 651 int64_read_value, /* recycle from int64 */ 652 int64_set_value, /* recycle from int64 */ 653 NULL, 654 NULL, /* FIXME */ 655 NULL /* FIXME */ 656 }; 657 658 static const TestTypeNodeClass string_0_class = { 659 DBUS_TYPE_STRING, 660 sizeof (TestTypeNode), 661 0, /* string length */ 662 NULL, 663 NULL, 664 string_write_value, 665 string_read_value, 666 string_set_value, 667 NULL, 668 NULL, 669 NULL 670 }; 671 672 static const TestTypeNodeClass string_1_class = { 673 DBUS_TYPE_STRING, 674 sizeof (TestTypeNode), 675 1, /* string length */ 676 NULL, 677 NULL, 678 string_write_value, 679 string_read_value, 680 string_set_value, 681 NULL, 682 NULL, 683 NULL 684 }; 685 686 /* with nul, a len 3 string should fill 4 bytes and thus is "special" */ 687 static const TestTypeNodeClass string_3_class = { 688 DBUS_TYPE_STRING, 689 sizeof (TestTypeNode), 690 3, /* string length */ 691 NULL, 692 NULL, 693 string_write_value, 694 string_read_value, 695 string_set_value, 696 NULL, 697 NULL, 698 NULL 699 }; 700 701 /* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */ 702 static const TestTypeNodeClass string_8_class = { 703 DBUS_TYPE_STRING, 704 sizeof (TestTypeNode), 705 8, /* string length */ 706 NULL, 707 NULL, 708 string_write_value, 709 string_read_value, 710 string_set_value, 711 NULL, 712 NULL, 713 NULL 714 }; 715 716 static const TestTypeNodeClass bool_class = { 717 DBUS_TYPE_BOOLEAN, 718 sizeof (TestTypeNode), 719 0, 720 NULL, 721 NULL, 722 bool_write_value, 723 bool_read_value, 724 bool_set_value, 725 NULL, 726 NULL, /* FIXME */ 727 NULL /* FIXME */ 728 }; 729 730 static const TestTypeNodeClass byte_class = { 731 DBUS_TYPE_BYTE, 732 sizeof (TestTypeNode), 733 0, 734 NULL, 735 NULL, 736 byte_write_value, 737 byte_read_value, 738 byte_set_value, 739 NULL, 740 NULL, /* FIXME */ 741 NULL /* FIXME */ 742 }; 743 744 static const TestTypeNodeClass double_class = { 745 DBUS_TYPE_DOUBLE, 746 sizeof (TestTypeNode), 747 0, 748 NULL, 749 NULL, 750 double_write_value, 751 double_read_value, 752 double_set_value, 753 NULL, 754 NULL, /* FIXME */ 755 NULL /* FIXME */ 756 }; 757 758 static const TestTypeNodeClass object_path_class = { 759 DBUS_TYPE_OBJECT_PATH, 760 sizeof (TestTypeNode), 761 0, 762 NULL, 763 NULL, 764 object_path_write_value, 765 object_path_read_value, 766 object_path_set_value, 767 NULL, 768 NULL, 769 NULL 770 }; 771 772 static const TestTypeNodeClass signature_class = { 773 DBUS_TYPE_SIGNATURE, 774 sizeof (TestTypeNode), 775 0, 776 NULL, 777 NULL, 778 signature_write_value, 779 signature_read_value, 780 signature_set_value, 781 NULL, 782 NULL, 783 NULL 784 }; 785 786 static const TestTypeNodeClass struct_1_class = { 787 DBUS_TYPE_STRUCT, 788 sizeof (TestTypeNodeContainer), 789 1, /* number of times children appear as fields */ 790 NULL, 791 container_destroy, 792 struct_write_value, 793 struct_read_value, 794 struct_set_value, 795 struct_build_signature, 796 NULL, 797 NULL 798 }; 799 800 static const TestTypeNodeClass struct_2_class = { 801 DBUS_TYPE_STRUCT, 802 sizeof (TestTypeNodeContainer), 803 2, /* number of times children appear as fields */ 804 NULL, 805 container_destroy, 806 struct_write_value, 807 struct_read_value, 808 struct_set_value, 809 struct_build_signature, 810 NULL, 811 NULL 812 }; 813 814 static const TestTypeNodeClass dict_1_class = { 815 DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */ 816 sizeof (TestTypeNodeContainer), 817 1, /* number of entries */ 818 NULL, 819 container_destroy, 820 dict_write_value, 821 dict_read_value, 822 dict_set_value, 823 dict_build_signature, 824 NULL, 825 NULL 826 }; 827 828 static dbus_bool_t arrays_write_fixed_in_blocks = FALSE; 829 830 static const TestTypeNodeClass array_0_class = { 831 DBUS_TYPE_ARRAY, 832 sizeof (TestTypeNodeContainer), 833 0, /* number of array elements */ 834 NULL, 835 container_destroy, 836 array_write_value, 837 array_read_value, 838 array_set_value, 839 array_build_signature, 840 NULL, 841 NULL 842 }; 843 844 static const TestTypeNodeClass array_1_class = { 845 DBUS_TYPE_ARRAY, 846 sizeof (TestTypeNodeContainer), 847 1, /* number of array elements */ 848 NULL, 849 container_destroy, 850 array_write_value, 851 array_read_value, 852 array_set_value, 853 array_build_signature, 854 NULL, 855 NULL 856 }; 857 858 static const TestTypeNodeClass array_2_class = { 859 DBUS_TYPE_ARRAY, 860 sizeof (TestTypeNodeContainer), 861 2, /* number of array elements */ 862 NULL, 863 container_destroy, 864 array_write_value, 865 array_read_value, 866 array_set_value, 867 array_build_signature, 868 NULL, 869 NULL 870 }; 871 872 static const TestTypeNodeClass array_9_class = { 873 DBUS_TYPE_ARRAY, 874 sizeof (TestTypeNodeContainer), 875 9, /* number of array elements */ 876 NULL, 877 container_destroy, 878 array_write_value, 879 array_read_value, 880 array_set_value, 881 array_build_signature, 882 NULL, 883 NULL 884 }; 885 886 static const TestTypeNodeClass variant_class = { 887 DBUS_TYPE_VARIANT, 888 sizeof (TestTypeNodeContainer), 889 0, 890 NULL, 891 container_destroy, 892 variant_write_value, 893 variant_read_value, 894 variant_set_value, 895 NULL, 896 NULL, 897 NULL 898 }; 899 900 static const TestTypeNodeClass* const 901 basic_nodes[] = { 902 &int16_class, 903 &uint16_class, 904 &int32_class, 905 &uint32_class, 906 &int64_class, 907 &uint64_class, 908 &bool_class, 909 &byte_class, 910 &double_class, 911 &string_0_class, 912 &string_1_class, 913 &string_3_class, 914 &string_8_class, 915 &object_path_class, 916 &signature_class 917 }; 918 #define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes)) 919 920 static const TestTypeNodeClass* const 921 container_nodes[] = { 922 &struct_1_class, 923 &array_1_class, 924 &struct_2_class, 925 &array_0_class, 926 &array_2_class, 927 &variant_class, 928 &dict_1_class /* last since we want struct and array before it */ 929 /* array_9_class is omitted on purpose, it's too slow; 930 * we only use it in one hardcoded test below 931 */ 932 }; 933 #define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes)) 934 935 static TestTypeNode* 936 node_new (const TestTypeNodeClass *klass) 937 { 938 TestTypeNode *node; 939 940 node = dbus_malloc0 (klass->instance_size); 941 if (node == NULL) 942 return NULL; 943 944 node->klass = klass; 945 946 if (klass->construct) 947 { 948 if (!(* klass->construct) (node)) 949 { 950 dbus_free (node); 951 return NULL; 952 } 953 } 954 955 return node; 956 } 957 958 static void 959 node_destroy (TestTypeNode *node) 960 { 961 if (node->klass->destroy) 962 (* node->klass->destroy) (node); 963 dbus_free (node); 964 } 965 966 static dbus_bool_t 967 node_write_value (TestTypeNode *node, 968 DataBlock *block, 969 DBusTypeWriter *writer, 970 int seed) 971 { 972 dbus_bool_t retval; 973 974 retval = (* node->klass->write_value) (node, block, writer, seed); 975 976 #if 0 977 /* Handy to see where things break, but too expensive to do all the time */ 978 data_block_verify (block); 979 #endif 980 981 return retval; 982 } 983 984 static dbus_bool_t 985 node_read_value (TestTypeNode *node, 986 DBusTypeReader *reader, 987 int seed) 988 { 989 /* DBusTypeReader restored; */ 990 991 if (!(* node->klass->read_value) (node, reader, seed)) 992 return FALSE; 993 994 return TRUE; 995 } 996 997 /* Warning: if this one fails due to OOM, it has side effects (can 998 * modify only some of the sub-values). OK in a test suite, but we 999 * never do this in real code. 1000 */ 1001 static dbus_bool_t 1002 node_set_value (TestTypeNode *node, 1003 DBusTypeReader *reader, 1004 DBusTypeReader *realign_root, 1005 int seed) 1006 { 1007 if (!(* node->klass->set_value) (node, reader, realign_root, seed)) 1008 return FALSE; 1009 1010 return TRUE; 1011 } 1012 1013 static dbus_bool_t 1014 node_build_signature (TestTypeNode *node, 1015 DBusString *str) 1016 { 1017 if (node->klass->build_signature) 1018 return (* node->klass->build_signature) (node, str); 1019 else 1020 return _dbus_string_append_byte (str, node->klass->typecode); 1021 } 1022 1023 static dbus_bool_t 1024 node_append_child (TestTypeNode *node, 1025 TestTypeNode *child) 1026 { 1027 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 1028 1029 _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer)); 1030 1031 if (!_dbus_list_append (&container->children, child)) 1032 _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 */ 1033 1034 return TRUE; 1035 } 1036 1037 static dbus_bool_t 1038 node_write_multi (TestTypeNode *node, 1039 DataBlock *block, 1040 DBusTypeWriter *writer, 1041 int seed, 1042 int n_copies) 1043 { 1044 dbus_bool_t retval; 1045 1046 _dbus_assert (node->klass->write_multi != NULL); 1047 retval = (* node->klass->write_multi) (node, block, writer, seed, n_copies); 1048 1049 #if 0 1050 /* Handy to see where things break, but too expensive to do all the time */ 1051 data_block_verify (block); 1052 #endif 1053 1054 return retval; 1055 } 1056 1057 static dbus_bool_t 1058 node_read_multi (TestTypeNode *node, 1059 DBusTypeReader *reader, 1060 int seed, 1061 int n_copies) 1062 { 1063 _dbus_assert (node->klass->read_multi != NULL); 1064 1065 if (!(* node->klass->read_multi) (node, reader, seed, n_copies)) 1066 return FALSE; 1067 1068 return TRUE; 1069 } 1070 1071 static int n_iterations_completed_total = 0; 1072 static int n_iterations_completed_this_test = 0; 1073 static int n_iterations_expected_this_test = 0; 1074 1075 typedef struct 1076 { 1077 const DBusString *signature; 1078 DataBlock *block; 1079 int type_offset; 1080 TestTypeNode **nodes; 1081 int n_nodes; 1082 } NodeIterationData; 1083 1084 static dbus_bool_t 1085 run_test_copy (NodeIterationData *nid) 1086 { 1087 DataBlock *src; 1088 DataBlock dest; 1089 dbus_bool_t retval; 1090 DBusTypeReader reader; 1091 DBusTypeWriter writer; 1092 1093 _dbus_verbose ("\n"); 1094 1095 src = nid->block; 1096 1097 retval = FALSE; 1098 1099 if (!data_block_init (&dest, src->byte_order, src->initial_offset)) 1100 return FALSE; 1101 1102 data_block_init_reader_writer (src, &reader, NULL); 1103 data_block_init_reader_writer (&dest, NULL, &writer); 1104 1105 /* DBusTypeWriter assumes it's writing into an existing signature, 1106 * so doesn't add nul on its own. We have to do that. 1107 */ 1108 if (!_dbus_string_insert_byte (&dest.signature, 1109 dest.initial_offset, '\0')) 1110 goto out; 1111 1112 if (!_dbus_type_writer_write_reader (&writer, &reader)) 1113 goto out; 1114 1115 /* Data blocks should now be identical */ 1116 if (!_dbus_string_equal (&src->signature, &dest.signature)) 1117 { 1118 _dbus_verbose ("SOURCE\n"); 1119 _dbus_verbose_bytes_of_string (&src->signature, 0, 1120 _dbus_string_get_length (&src->signature)); 1121 _dbus_verbose ("DEST\n"); 1122 _dbus_verbose_bytes_of_string (&dest.signature, 0, 1123 _dbus_string_get_length (&dest.signature)); 1124 _dbus_assert_not_reached ("signatures did not match"); 1125 } 1126 1127 if (!_dbus_string_equal (&src->body, &dest.body)) 1128 { 1129 _dbus_verbose ("SOURCE\n"); 1130 _dbus_verbose_bytes_of_string (&src->body, 0, 1131 _dbus_string_get_length (&src->body)); 1132 _dbus_verbose ("DEST\n"); 1133 _dbus_verbose_bytes_of_string (&dest.body, 0, 1134 _dbus_string_get_length (&dest.body)); 1135 _dbus_assert_not_reached ("bodies did not match"); 1136 } 1137 1138 retval = TRUE; 1139 1140 out: 1141 1142 data_block_free (&dest); 1143 1144 return retval; 1145 } 1146 1147 static dbus_bool_t 1148 run_test_values_only_write (NodeIterationData *nid) 1149 { 1150 DBusTypeReader reader; 1151 DBusTypeWriter writer; 1152 int i; 1153 dbus_bool_t retval; 1154 int sig_len; 1155 1156 _dbus_verbose ("\n"); 1157 1158 retval = FALSE; 1159 1160 data_block_reset (nid->block); 1161 1162 sig_len = _dbus_string_get_length (nid->signature); 1163 1164 _dbus_type_writer_init_values_only (&writer, 1165 nid->block->byte_order, 1166 nid->signature, 0, 1167 &nid->block->body, 1168 _dbus_string_get_length (&nid->block->body) - N_FENCE_BYTES); 1169 _dbus_type_reader_init (&reader, 1170 nid->block->byte_order, 1171 nid->signature, 0, 1172 &nid->block->body, 1173 nid->block->initial_offset); 1174 1175 i = 0; 1176 while (i < nid->n_nodes) 1177 { 1178 if (!node_write_value (nid->nodes[i], nid->block, &writer, i)) 1179 goto out; 1180 1181 ++i; 1182 } 1183 1184 /* if we wrote any typecodes then this would fail */ 1185 _dbus_assert (sig_len == _dbus_string_get_length (nid->signature)); 1186 1187 /* But be sure we wrote out the values correctly */ 1188 i = 0; 1189 while (i < nid->n_nodes) 1190 { 1191 if (!node_read_value (nid->nodes[i], &reader, i)) 1192 goto out; 1193 1194 if (i + 1 == nid->n_nodes) 1195 NEXT_EXPECTING_FALSE (&reader); 1196 else 1197 NEXT_EXPECTING_TRUE (&reader); 1198 1199 ++i; 1200 } 1201 1202 retval = TRUE; 1203 1204 out: 1205 data_block_reset (nid->block); 1206 return retval; 1207 } 1208 1209 /* offset the seed for setting, so we set different numbers than 1210 * we originally wrote. Don't offset by a huge number since in 1211 * some cases it's value = possibilities[seed % n_possibilities] 1212 * and we don't want to wrap around. bool_from_seed 1213 * is just seed % 2 even. 1214 */ 1215 #define SET_SEED 1 1216 static dbus_bool_t 1217 run_test_set_values (NodeIterationData *nid) 1218 { 1219 DBusTypeReader reader; 1220 DBusTypeReader realign_root; 1221 dbus_bool_t retval; 1222 int i; 1223 1224 _dbus_verbose ("\n"); 1225 1226 retval = FALSE; 1227 1228 data_block_init_reader_writer (nid->block, 1229 &reader, NULL); 1230 1231 realign_root = reader; 1232 1233 i = 0; 1234 while (i < nid->n_nodes) 1235 { 1236 if (!node_set_value (nid->nodes[i], 1237 &reader, &realign_root, 1238 i + SET_SEED)) 1239 goto out; 1240 1241 if (i + 1 == nid->n_nodes) 1242 NEXT_EXPECTING_FALSE (&reader); 1243 else 1244 NEXT_EXPECTING_TRUE (&reader); 1245 1246 ++i; 1247 } 1248 1249 /* Check that the new values were set */ 1250 1251 reader = realign_root; 1252 1253 i = 0; 1254 while (i < nid->n_nodes) 1255 { 1256 if (!node_read_value (nid->nodes[i], &reader, 1257 i + SET_SEED)) 1258 goto out; 1259 1260 if (i + 1 == nid->n_nodes) 1261 NEXT_EXPECTING_FALSE (&reader); 1262 else 1263 NEXT_EXPECTING_TRUE (&reader); 1264 1265 ++i; 1266 } 1267 1268 retval = TRUE; 1269 1270 out: 1271 return retval; 1272 } 1273 1274 static dbus_bool_t 1275 run_test_delete_values (NodeIterationData *nid) 1276 { 1277 DBusTypeReader reader; 1278 dbus_bool_t retval; 1279 int t; 1280 1281 _dbus_verbose ("\n"); 1282 1283 retval = FALSE; 1284 1285 data_block_init_reader_writer (nid->block, 1286 &reader, NULL); 1287 1288 while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID) 1289 { 1290 /* Right now, deleting only works on array elements. We delete 1291 * all array elements, and then verify that there aren't any 1292 * left. 1293 */ 1294 if (t == DBUS_TYPE_ARRAY) 1295 { 1296 DBusTypeReader array; 1297 int n_elements; 1298 int elem_type; 1299 1300 _dbus_type_reader_recurse (&reader, &array); 1301 n_elements = 0; 1302 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 1303 { 1304 n_elements += 1; 1305 _dbus_type_reader_next (&array); 1306 } 1307 1308 /* reset to start of array */ 1309 _dbus_type_reader_recurse (&reader, &array); 1310 _dbus_verbose ("recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d\n", 1311 reader.value_pos, array.value_pos, array.u.array.start_pos); 1312 while ((elem_type = _dbus_type_reader_get_current_type (&array)) != DBUS_TYPE_INVALID) 1313 { 1314 /* We don't want to always delete from the same part of the array. */ 1315 static int cycle = 0; 1316 int elem; 1317 1318 _dbus_assert (n_elements > 0); 1319 1320 elem = cycle; 1321 if (elem == 3 || elem >= n_elements) /* end of array */ 1322 elem = n_elements - 1; 1323 1324 _dbus_verbose ("deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d\n", 1325 elem, n_elements, _dbus_type_to_string (elem_type), 1326 cycle, reader.value_pos, array.value_pos); 1327 while (elem > 0) 1328 { 1329 if (!_dbus_type_reader_next (&array)) 1330 _dbus_assert_not_reached ("should have had another element\n"); 1331 --elem; 1332 } 1333 1334 if (!_dbus_type_reader_delete (&array, &reader)) 1335 goto out; 1336 1337 n_elements -= 1; 1338 1339 /* reset */ 1340 _dbus_type_reader_recurse (&reader, &array); 1341 1342 if (cycle > 2) 1343 cycle = 0; 1344 else 1345 cycle += 1; 1346 } 1347 } 1348 _dbus_type_reader_next (&reader); 1349 } 1350 1351 /* Check that there are no array elements left */ 1352 data_block_init_reader_writer (nid->block, 1353 &reader, NULL); 1354 1355 while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID) 1356 { 1357 _dbus_type_reader_next (&reader); 1358 } 1359 1360 retval = TRUE; 1361 1362 out: 1363 return retval; 1364 } 1365 1366 static dbus_bool_t 1367 run_test_nodes_iteration (void *data) 1368 { 1369 NodeIterationData *nid = data; 1370 DBusTypeReader reader; 1371 DBusTypeWriter writer; 1372 int i; 1373 dbus_bool_t retval; 1374 1375 /* Stuff to do: 1376 * 1. write the value 1377 * 2. strcmp-compare with the signature we built 1378 * 3. read the value 1379 * 4. type-iterate the signature and the value and see if they are the same type-wise 1380 */ 1381 retval = FALSE; 1382 1383 data_block_init_reader_writer (nid->block, 1384 &reader, &writer); 1385 1386 /* DBusTypeWriter assumes it's writing into an existing signature, 1387 * so doesn't add nul on its own. We have to do that. 1388 */ 1389 if (!_dbus_string_insert_byte (&nid->block->signature, 1390 nid->type_offset, '\0')) 1391 goto out; 1392 1393 i = 0; 1394 while (i < nid->n_nodes) 1395 { 1396 if (!node_write_value (nid->nodes[i], nid->block, &writer, i)) 1397 goto out; 1398 1399 ++i; 1400 } 1401 1402 if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature), 1403 &nid->block->signature, nid->type_offset)) 1404 { 1405 _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n", 1406 _dbus_string_get_const_data (nid->signature), 1407 _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0), 1408 nid->type_offset); 1409 _dbus_assert_not_reached ("wrong signature"); 1410 } 1411 1412 i = 0; 1413 while (i < nid->n_nodes) 1414 { 1415 if (!node_read_value (nid->nodes[i], &reader, i)) 1416 goto out; 1417 1418 if (i + 1 == nid->n_nodes) 1419 NEXT_EXPECTING_FALSE (&reader); 1420 else 1421 NEXT_EXPECTING_TRUE (&reader); 1422 1423 ++i; 1424 } 1425 1426 if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS) 1427 { 1428 /* this set values test uses code from copy and 1429 * values_only_write so would ideally be last so you get a 1430 * simpler test case for problems with copying or values_only 1431 * writing; but it also needs an already-written DataBlock so it 1432 * has to go first. Comment it out if it breaks, and see if the 1433 * later tests also break - debug them first if so. 1434 */ 1435 if (!run_test_set_values (nid)) 1436 goto out; 1437 1438 if (!run_test_delete_values (nid)) 1439 goto out; 1440 1441 if (!run_test_copy (nid)) 1442 goto out; 1443 1444 if (!run_test_values_only_write (nid)) 1445 goto out; 1446 } 1447 1448 /* FIXME type-iterate both signature and value and compare the resulting 1449 * tree to the node tree perhaps 1450 */ 1451 1452 retval = TRUE; 1453 1454 out: 1455 1456 data_block_reset (nid->block); 1457 1458 return retval; 1459 } 1460 1461 static void 1462 run_test_nodes_in_one_configuration (TestTypeNode **nodes, 1463 int n_nodes, 1464 const DBusString *signature, 1465 int byte_order, 1466 int initial_offset) 1467 { 1468 DataBlock block; 1469 NodeIterationData nid; 1470 1471 if (!data_block_init (&block, byte_order, initial_offset)) 1472 _dbus_assert_not_reached ("no memory"); 1473 1474 nid.signature = signature; 1475 nid.block = █ 1476 nid.type_offset = initial_offset; 1477 nid.nodes = nodes; 1478 nid.n_nodes = n_nodes; 1479 1480 if (TEST_OOM_HANDLING && 1481 n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS) 1482 { 1483 _dbus_test_oom_handling ("running test node", 1484 run_test_nodes_iteration, 1485 &nid); 1486 } 1487 else 1488 { 1489 if (!run_test_nodes_iteration (&nid)) 1490 _dbus_assert_not_reached ("no memory"); 1491 } 1492 1493 data_block_free (&block); 1494 } 1495 1496 static void 1497 run_test_nodes (TestTypeNode **nodes, 1498 int n_nodes) 1499 { 1500 int i; 1501 DBusString signature; 1502 1503 if (!_dbus_string_init (&signature)) 1504 _dbus_assert_not_reached ("no memory"); 1505 1506 i = 0; 1507 while (i < n_nodes) 1508 { 1509 if (! node_build_signature (nodes[i], &signature)) 1510 _dbus_assert_not_reached ("no memory"); 1511 1512 ++i; 1513 } 1514 1515 _dbus_verbose (">>> test nodes with signature '%s'\n", 1516 _dbus_string_get_const_data (&signature)); 1517 1518 i = 0; 1519 while (i <= MAX_INITIAL_OFFSET) 1520 { 1521 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature, 1522 DBUS_LITTLE_ENDIAN, i); 1523 run_test_nodes_in_one_configuration (nodes, n_nodes, &signature, 1524 DBUS_BIG_ENDIAN, i); 1525 1526 ++i; 1527 } 1528 1529 n_iterations_completed_this_test += 1; 1530 n_iterations_completed_total += 1; 1531 1532 if (n_iterations_completed_this_test == n_iterations_expected_this_test) 1533 { 1534 fprintf (stderr, " 100%% %d this test (%d cumulative)\n", 1535 n_iterations_completed_this_test, 1536 n_iterations_completed_total); 1537 } 1538 /* this happens to turn out well with mod == 1 */ 1539 else if ((n_iterations_completed_this_test % 1540 (int)(n_iterations_expected_this_test / 10.0)) == 1) 1541 { 1542 fprintf (stderr, " %d%% ", (int) (n_iterations_completed_this_test / (double) n_iterations_expected_this_test * 100)); 1543 } 1544 1545 _dbus_string_free (&signature); 1546 } 1547 1548 #define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS) 1549 1550 static TestTypeNode* 1551 value_generator (int *ip) 1552 { 1553 int i = *ip; 1554 const TestTypeNodeClass *child_klass; 1555 const TestTypeNodeClass *container_klass; 1556 TestTypeNode *child; 1557 TestTypeNode *node; 1558 1559 _dbus_assert (i <= N_VALUES); 1560 1561 if (i == N_VALUES) 1562 { 1563 return NULL; 1564 } 1565 else if (i < N_BASICS) 1566 { 1567 node = node_new (basic_nodes[i]); 1568 } 1569 else 1570 { 1571 /* imagine an array: 1572 * container 0 of basic 0 1573 * container 0 of basic 1 1574 * container 0 of basic 2 1575 * container 1 of basic 0 1576 * container 1 of basic 1 1577 * container 1 of basic 2 1578 */ 1579 i -= N_BASICS; 1580 1581 container_klass = container_nodes[i / N_BASICS]; 1582 child_klass = basic_nodes[i % N_BASICS]; 1583 1584 node = node_new (container_klass); 1585 child = node_new (child_klass); 1586 1587 node_append_child (node, child); 1588 } 1589 1590 *ip += 1; /* increment the generator */ 1591 1592 return node; 1593 } 1594 1595 static void 1596 build_body (TestTypeNode **nodes, 1597 int n_nodes, 1598 int byte_order, 1599 DBusString *signature, 1600 DBusString *body) 1601 { 1602 int i; 1603 DataBlock block; 1604 DBusTypeReader reader; 1605 DBusTypeWriter writer; 1606 1607 i = 0; 1608 while (i < n_nodes) 1609 { 1610 if (! node_build_signature (nodes[i], signature)) 1611 _dbus_assert_not_reached ("no memory"); 1612 1613 ++i; 1614 } 1615 1616 if (!data_block_init (&block, byte_order, 0)) 1617 _dbus_assert_not_reached ("no memory"); 1618 1619 data_block_init_reader_writer (&block, 1620 &reader, &writer); 1621 1622 /* DBusTypeWriter assumes it's writing into an existing signature, 1623 * so doesn't add nul on its own. We have to do that. 1624 */ 1625 if (!_dbus_string_insert_byte (&block.signature, 1626 0, '\0')) 1627 _dbus_assert_not_reached ("no memory"); 1628 1629 i = 0; 1630 while (i < n_nodes) 1631 { 1632 if (!node_write_value (nodes[i], &block, &writer, i)) 1633 _dbus_assert_not_reached ("no memory"); 1634 1635 ++i; 1636 } 1637 1638 if (!_dbus_string_copy_len (&block.body, 0, 1639 _dbus_string_get_length (&block.body) - N_FENCE_BYTES, 1640 body, 0)) 1641 _dbus_assert_not_reached ("oom"); 1642 1643 data_block_free (&block); 1644 } 1645 1646 dbus_bool_t 1647 dbus_internal_do_not_use_generate_bodies (int sequence, 1648 int byte_order, 1649 DBusString *signature, 1650 DBusString *body) 1651 { 1652 TestTypeNode *nodes[1]; 1653 int i; 1654 int n_nodes; 1655 1656 nodes[0] = value_generator (&sequence); 1657 1658 if (nodes[0] == NULL) 1659 return FALSE; 1660 1661 n_nodes = 1; 1662 1663 build_body (nodes, n_nodes, byte_order, signature, body); 1664 1665 1666 i = 0; 1667 while (i < n_nodes) 1668 { 1669 node_destroy (nodes[i]); 1670 ++i; 1671 } 1672 1673 return TRUE; 1674 } 1675 1676 static void 1677 make_and_run_values_inside_container (const TestTypeNodeClass *container_klass, 1678 int n_nested) 1679 { 1680 TestTypeNode *root; 1681 TestTypeNode *container; 1682 TestTypeNode *child; 1683 int i; 1684 1685 root = node_new (container_klass); 1686 container = root; 1687 for (i = 1; i < n_nested; i++) 1688 { 1689 child = node_new (container_klass); 1690 node_append_child (container, child); 1691 container = child; 1692 } 1693 1694 /* container should now be the most-nested container */ 1695 1696 i = 0; 1697 while ((child = value_generator (&i))) 1698 { 1699 node_append_child (container, child); 1700 1701 run_test_nodes (&root, 1); 1702 1703 _dbus_list_clear (&((TestTypeNodeContainer*)container)->children); 1704 node_destroy (child); 1705 } 1706 1707 node_destroy (root); 1708 } 1709 1710 static void 1711 start_next_test (const char *format, 1712 int expected) 1713 { 1714 n_iterations_completed_this_test = 0; 1715 n_iterations_expected_this_test = expected; 1716 1717 fprintf (stderr, ">>> >>> "); 1718 fprintf (stderr, format, 1719 n_iterations_expected_this_test); 1720 } 1721 1722 static void 1723 make_and_run_test_nodes (void) 1724 { 1725 int i, j, k, m; 1726 1727 /* We try to do this in order of "complicatedness" so that test 1728 * failures tend to show up in the simplest test case that 1729 * demonstrates the failure. There are also some tests that run 1730 * more than once for this reason, first while going through simple 1731 * cases, second while going through a broader range of complex 1732 * cases. 1733 */ 1734 /* Each basic node. The basic nodes should include: 1735 * 1736 * - each fixed-size type (in such a way that it has different values each time, 1737 * so we can tell if we mix two of them up) 1738 * - strings of various lengths 1739 * - object path 1740 * - signature 1741 */ 1742 /* Each container node. The container nodes should include: 1743 * 1744 * struct with 1 and 2 copies of the contained item 1745 * array with 0, 1, 2 copies of the contained item 1746 * variant 1747 */ 1748 /* Let a "value" be a basic node, or a container containing a single basic node. 1749 * Let n_values be the number of such values i.e. (n_container * n_basic + n_basic) 1750 * When iterating through all values to make combinations, do the basic types 1751 * first and the containers second. 1752 */ 1753 /* Each item is shown with its number of iterations to complete so 1754 * we can keep a handle on this unit test 1755 */ 1756 1757 /* FIXME test just an empty body, no types at all */ 1758 1759 start_next_test ("Each value by itself %d iterations\n", N_VALUES); 1760 { 1761 TestTypeNode *node; 1762 i = 0; 1763 while ((node = value_generator (&i))) 1764 { 1765 run_test_nodes (&node, 1); 1766 1767 node_destroy (node); 1768 } 1769 } 1770 1771 start_next_test ("Each value by itself with arrays as blocks %d iterations\n", N_VALUES); 1772 arrays_write_fixed_in_blocks = TRUE; 1773 { 1774 TestTypeNode *node; 1775 i = 0; 1776 while ((node = value_generator (&i))) 1777 { 1778 run_test_nodes (&node, 1); 1779 1780 node_destroy (node); 1781 } 1782 } 1783 arrays_write_fixed_in_blocks = FALSE; 1784 1785 start_next_test ("All values in one big toplevel %d iteration\n", 1); 1786 { 1787 TestTypeNode *nodes[N_VALUES]; 1788 1789 i = 0; 1790 while ((nodes[i] = value_generator (&i))) 1791 ; 1792 1793 run_test_nodes (nodes, N_VALUES); 1794 1795 for (i = 0; i < N_VALUES; i++) 1796 node_destroy (nodes[i]); 1797 } 1798 1799 start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n", 1800 N_VALUES * N_VALUES); 1801 { 1802 TestTypeNode *nodes[2]; 1803 1804 i = 0; 1805 while ((nodes[0] = value_generator (&i))) 1806 { 1807 j = 0; 1808 while ((nodes[1] = value_generator (&j))) 1809 { 1810 run_test_nodes (nodes, 2); 1811 1812 node_destroy (nodes[1]); 1813 } 1814 1815 node_destroy (nodes[0]); 1816 } 1817 } 1818 1819 start_next_test ("Each container containing each value %d iterations\n", 1820 N_CONTAINERS * N_VALUES); 1821 for (i = 0; i < N_CONTAINERS; i++) 1822 { 1823 const TestTypeNodeClass *container_klass = container_nodes[i]; 1824 1825 make_and_run_values_inside_container (container_klass, 1); 1826 } 1827 1828 start_next_test ("Each container containing each value with arrays as blocks %d iterations\n", 1829 N_CONTAINERS * N_VALUES); 1830 arrays_write_fixed_in_blocks = TRUE; 1831 for (i = 0; i < N_CONTAINERS; i++) 1832 { 1833 const TestTypeNodeClass *container_klass = container_nodes[i]; 1834 1835 make_and_run_values_inside_container (container_klass, 1); 1836 } 1837 arrays_write_fixed_in_blocks = FALSE; 1838 1839 start_next_test ("Each container of same container of each value %d iterations\n", 1840 N_CONTAINERS * N_VALUES); 1841 for (i = 0; i < N_CONTAINERS; i++) 1842 { 1843 const TestTypeNodeClass *container_klass = container_nodes[i]; 1844 1845 make_and_run_values_inside_container (container_klass, 2); 1846 } 1847 1848 start_next_test ("Each container of same container of same container of each value %d iterations\n", 1849 N_CONTAINERS * N_VALUES); 1850 for (i = 0; i < N_CONTAINERS; i++) 1851 { 1852 const TestTypeNodeClass *container_klass = container_nodes[i]; 1853 1854 make_and_run_values_inside_container (container_klass, 3); 1855 } 1856 1857 start_next_test ("Each value,value pair inside a struct %d iterations\n", 1858 N_VALUES * N_VALUES); 1859 { 1860 TestTypeNode *val1, *val2; 1861 TestTypeNode *node; 1862 1863 node = node_new (&struct_1_class); 1864 1865 i = 0; 1866 while ((val1 = value_generator (&i))) 1867 { 1868 j = 0; 1869 while ((val2 = value_generator (&j))) 1870 { 1871 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 1872 1873 node_append_child (node, val1); 1874 node_append_child (node, val2); 1875 1876 run_test_nodes (&node, 1); 1877 1878 _dbus_list_clear (&container->children); 1879 node_destroy (val2); 1880 } 1881 node_destroy (val1); 1882 } 1883 node_destroy (node); 1884 } 1885 1886 start_next_test ("All values in one big struct %d iteration\n", 1887 1); 1888 { 1889 TestTypeNode *node; 1890 TestTypeNode *child; 1891 1892 node = node_new (&struct_1_class); 1893 1894 i = 0; 1895 while ((child = value_generator (&i))) 1896 node_append_child (node, child); 1897 1898 run_test_nodes (&node, 1); 1899 1900 node_destroy (node); 1901 } 1902 1903 start_next_test ("Each value in a large array %d iterations\n", 1904 N_VALUES); 1905 { 1906 TestTypeNode *val; 1907 TestTypeNode *node; 1908 1909 node = node_new (&array_9_class); 1910 1911 i = 0; 1912 while ((val = value_generator (&i))) 1913 { 1914 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 1915 1916 node_append_child (node, val); 1917 1918 run_test_nodes (&node, 1); 1919 1920 _dbus_list_clear (&container->children); 1921 node_destroy (val); 1922 } 1923 1924 node_destroy (node); 1925 } 1926 1927 start_next_test ("Each container of each container of each value %d iterations\n", 1928 N_CONTAINERS * N_CONTAINERS * N_VALUES); 1929 for (i = 0; i < N_CONTAINERS; i++) 1930 { 1931 const TestTypeNodeClass *outer_container_klass = container_nodes[i]; 1932 TestTypeNode *outer_container = node_new (outer_container_klass); 1933 1934 for (j = 0; j < N_CONTAINERS; j++) 1935 { 1936 TestTypeNode *child; 1937 const TestTypeNodeClass *inner_container_klass = container_nodes[j]; 1938 TestTypeNode *inner_container = node_new (inner_container_klass); 1939 1940 node_append_child (outer_container, inner_container); 1941 1942 m = 0; 1943 while ((child = value_generator (&m))) 1944 { 1945 node_append_child (inner_container, child); 1946 1947 run_test_nodes (&outer_container, 1); 1948 1949 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children); 1950 node_destroy (child); 1951 } 1952 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children); 1953 node_destroy (inner_container); 1954 } 1955 node_destroy (outer_container); 1956 } 1957 1958 start_next_test ("Each container of each container of each container of each value %d iterations\n", 1959 N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES); 1960 for (i = 0; i < N_CONTAINERS; i++) 1961 { 1962 const TestTypeNodeClass *outer_container_klass = container_nodes[i]; 1963 TestTypeNode *outer_container = node_new (outer_container_klass); 1964 1965 for (j = 0; j < N_CONTAINERS; j++) 1966 { 1967 const TestTypeNodeClass *inner_container_klass = container_nodes[j]; 1968 TestTypeNode *inner_container = node_new (inner_container_klass); 1969 1970 node_append_child (outer_container, inner_container); 1971 1972 for (k = 0; k < N_CONTAINERS; k++) 1973 { 1974 TestTypeNode *child; 1975 const TestTypeNodeClass *center_container_klass = container_nodes[k]; 1976 TestTypeNode *center_container = node_new (center_container_klass); 1977 1978 node_append_child (inner_container, center_container); 1979 1980 m = 0; 1981 while ((child = value_generator (&m))) 1982 { 1983 node_append_child (center_container, child); 1984 1985 run_test_nodes (&outer_container, 1); 1986 1987 _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children); 1988 node_destroy (child); 1989 } 1990 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children); 1991 node_destroy (center_container); 1992 } 1993 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children); 1994 node_destroy (inner_container); 1995 } 1996 node_destroy (outer_container); 1997 } 1998 1999 #if 0 2000 /* This one takes a really long time, so comment it out for now */ 2001 start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n", 2002 N_VALUES * N_VALUES * N_VALUES); 2003 { 2004 TestTypeNode *nodes[3]; 2005 2006 i = 0; 2007 while ((nodes[0] = value_generator (&i))) 2008 { 2009 j = 0; 2010 while ((nodes[1] = value_generator (&j))) 2011 { 2012 k = 0; 2013 while ((nodes[2] = value_generator (&k))) 2014 { 2015 run_test_nodes (nodes, 3); 2016 2017 node_destroy (nodes[2]); 2018 } 2019 node_destroy (nodes[1]); 2020 } 2021 node_destroy (nodes[0]); 2022 } 2023 } 2024 #endif /* #if 0 expensive test */ 2025 2026 fprintf (stderr, "%d total iterations of recursive marshaling tests\n", 2027 n_iterations_completed_total); 2028 fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n", 2029 MAX_INITIAL_OFFSET); 2030 fprintf (stderr, "out of memory handling %s tested\n", 2031 TEST_OOM_HANDLING ? "was" : "was not"); 2032 } 2033 2034 dbus_bool_t 2035 _dbus_marshal_recursive_test (void) 2036 { 2037 make_and_run_test_nodes (); 2038 2039 return TRUE; 2040 } 2041 2042 /* 2043 * 2044 * 2045 * Implementations of each type node class 2046 * 2047 * 2048 * 2049 */ 2050 #define MAX_MULTI_COUNT 5 2051 2052 #define SAMPLE_INT16 1234 2053 #define SAMPLE_INT16_ALTERNATE 6785 2054 static dbus_int16_t 2055 int16_from_seed (int seed) 2056 { 2057 /* Generate an integer value that's predictable from seed. We could 2058 * just use seed itself, but that would only ever touch one byte of 2059 * the int so would miss some kinds of bug. 2060 */ 2061 dbus_int16_t v; 2062 2063 v = 42; /* just to quiet compiler afaik */ 2064 switch (seed % 5) 2065 { 2066 case 0: 2067 v = SAMPLE_INT16; 2068 break; 2069 case 1: 2070 v = SAMPLE_INT16_ALTERNATE; 2071 break; 2072 case 2: 2073 v = -1; 2074 break; 2075 case 3: 2076 v = _DBUS_INT16_MAX; 2077 break; 2078 case 4: 2079 v = 1; 2080 break; 2081 } 2082 2083 if (seed > 1) 2084 v *= seed; /* wraps around eventually, which is fine */ 2085 2086 return v; 2087 } 2088 2089 static dbus_bool_t 2090 int16_write_value (TestTypeNode *node, 2091 DataBlock *block, 2092 DBusTypeWriter *writer, 2093 int seed) 2094 { 2095 /* also used for uint16 */ 2096 dbus_int16_t v; 2097 2098 v = int16_from_seed (seed); 2099 2100 return _dbus_type_writer_write_basic (writer, 2101 node->klass->typecode, 2102 &v); 2103 } 2104 2105 static dbus_bool_t 2106 int16_read_value (TestTypeNode *node, 2107 DBusTypeReader *reader, 2108 int seed) 2109 { 2110 /* also used for uint16 */ 2111 dbus_int16_t v; 2112 2113 check_expected_type (reader, node->klass->typecode); 2114 2115 _dbus_type_reader_read_basic (reader, 2116 (dbus_int16_t*) &v); 2117 2118 _dbus_assert (v == int16_from_seed (seed)); 2119 2120 return TRUE; 2121 } 2122 2123 static dbus_bool_t 2124 int16_set_value (TestTypeNode *node, 2125 DBusTypeReader *reader, 2126 DBusTypeReader *realign_root, 2127 int seed) 2128 { 2129 /* also used for uint16 */ 2130 dbus_int16_t v; 2131 2132 v = int16_from_seed (seed); 2133 2134 return _dbus_type_reader_set_basic (reader, 2135 &v, 2136 realign_root); 2137 } 2138 2139 static dbus_bool_t 2140 int16_write_multi (TestTypeNode *node, 2141 DataBlock *block, 2142 DBusTypeWriter *writer, 2143 int seed, 2144 int count) 2145 { 2146 /* also used for uint16 */ 2147 dbus_int16_t values[MAX_MULTI_COUNT]; 2148 dbus_int16_t *v_ARRAY_INT16 = values; 2149 int i; 2150 2151 for (i = 0; i < count; ++i) 2152 values[i] = int16_from_seed (seed + i); 2153 2154 return _dbus_type_writer_write_fixed_multi (writer, 2155 node->klass->typecode, 2156 &v_ARRAY_INT16, count); 2157 } 2158 2159 static dbus_bool_t 2160 int16_read_multi (TestTypeNode *node, 2161 DBusTypeReader *reader, 2162 int seed, 2163 int count) 2164 { 2165 /* also used for uint16 */ 2166 dbus_int16_t *values; 2167 int n_elements; 2168 int i; 2169 2170 check_expected_type (reader, node->klass->typecode); 2171 2172 _dbus_type_reader_read_fixed_multi (reader, 2173 &values, 2174 &n_elements); 2175 2176 if (n_elements != count) 2177 _dbus_warn ("got %d elements expected %d\n", n_elements, count); 2178 _dbus_assert (n_elements == count); 2179 2180 for (i = 0; i < count; i++) 2181 _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order, 2182 (const unsigned char*)values + (i * 2))) == 2183 int16_from_seed (seed + i)); 2184 2185 return TRUE; 2186 } 2187 2188 2189 #define SAMPLE_INT32 12345678 2190 #define SAMPLE_INT32_ALTERNATE 53781429 2191 static dbus_int32_t 2192 int32_from_seed (int seed) 2193 { 2194 /* Generate an integer value that's predictable from seed. We could 2195 * just use seed itself, but that would only ever touch one byte of 2196 * the int so would miss some kinds of bug. 2197 */ 2198 dbus_int32_t v; 2199 2200 v = 42; /* just to quiet compiler afaik */ 2201 switch (seed % 5) 2202 { 2203 case 0: 2204 v = SAMPLE_INT32; 2205 break; 2206 case 1: 2207 v = SAMPLE_INT32_ALTERNATE; 2208 break; 2209 case 2: 2210 v = -1; 2211 break; 2212 case 3: 2213 v = _DBUS_INT_MAX; 2214 break; 2215 case 4: 2216 v = 1; 2217 break; 2218 } 2219 2220 if (seed > 1) 2221 v *= seed; /* wraps around eventually, which is fine */ 2222 2223 return v; 2224 } 2225 2226 static dbus_bool_t 2227 int32_write_value (TestTypeNode *node, 2228 DataBlock *block, 2229 DBusTypeWriter *writer, 2230 int seed) 2231 { 2232 /* also used for uint32 */ 2233 dbus_int32_t v; 2234 2235 v = int32_from_seed (seed); 2236 2237 return _dbus_type_writer_write_basic (writer, 2238 node->klass->typecode, 2239 &v); 2240 } 2241 2242 static dbus_bool_t 2243 int32_read_value (TestTypeNode *node, 2244 DBusTypeReader *reader, 2245 int seed) 2246 { 2247 /* also used for uint32 */ 2248 dbus_int32_t v; 2249 2250 check_expected_type (reader, node->klass->typecode); 2251 2252 _dbus_type_reader_read_basic (reader, 2253 (dbus_int32_t*) &v); 2254 2255 _dbus_assert (v == int32_from_seed (seed)); 2256 2257 return TRUE; 2258 } 2259 2260 static dbus_bool_t 2261 int32_set_value (TestTypeNode *node, 2262 DBusTypeReader *reader, 2263 DBusTypeReader *realign_root, 2264 int seed) 2265 { 2266 /* also used for uint32 */ 2267 dbus_int32_t v; 2268 2269 v = int32_from_seed (seed); 2270 2271 return _dbus_type_reader_set_basic (reader, 2272 &v, 2273 realign_root); 2274 } 2275 2276 static dbus_bool_t 2277 int32_write_multi (TestTypeNode *node, 2278 DataBlock *block, 2279 DBusTypeWriter *writer, 2280 int seed, 2281 int count) 2282 { 2283 /* also used for uint32 */ 2284 dbus_int32_t values[MAX_MULTI_COUNT]; 2285 dbus_int32_t *v_ARRAY_INT32 = values; 2286 int i; 2287 2288 for (i = 0; i < count; ++i) 2289 values[i] = int32_from_seed (seed + i); 2290 2291 return _dbus_type_writer_write_fixed_multi (writer, 2292 node->klass->typecode, 2293 &v_ARRAY_INT32, count); 2294 } 2295 2296 static dbus_bool_t 2297 int32_read_multi (TestTypeNode *node, 2298 DBusTypeReader *reader, 2299 int seed, 2300 int count) 2301 { 2302 /* also used for uint32 */ 2303 dbus_int32_t *values; 2304 int n_elements; 2305 int i; 2306 2307 check_expected_type (reader, node->klass->typecode); 2308 2309 _dbus_type_reader_read_fixed_multi (reader, 2310 &values, 2311 &n_elements); 2312 2313 if (n_elements != count) 2314 _dbus_warn ("got %d elements expected %d\n", n_elements, count); 2315 _dbus_assert (n_elements == count); 2316 2317 for (i = 0; i < count; i++) 2318 _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order, 2319 (const unsigned char*)values + (i * 4))) == 2320 int32_from_seed (seed + i)); 2321 2322 return TRUE; 2323 } 2324 2325 #ifdef DBUS_HAVE_INT64 2326 static dbus_int64_t 2327 int64_from_seed (int seed) 2328 { 2329 dbus_int32_t v32; 2330 dbus_int64_t v; 2331 2332 v32 = int32_from_seed (seed); 2333 2334 v = - (dbus_int32_t) ~ v32; 2335 v |= (((dbus_int64_t)v32) << 32); 2336 2337 return v; 2338 } 2339 #endif 2340 2341 static dbus_bool_t 2342 int64_write_value (TestTypeNode *node, 2343 DataBlock *block, 2344 DBusTypeWriter *writer, 2345 int seed) 2346 { 2347 #ifdef DBUS_HAVE_INT64 2348 /* also used for uint64 */ 2349 dbus_int64_t v; 2350 2351 v = int64_from_seed (seed); 2352 2353 return _dbus_type_writer_write_basic (writer, 2354 node->klass->typecode, 2355 &v); 2356 #else 2357 return TRUE; 2358 #endif 2359 } 2360 2361 static dbus_bool_t 2362 int64_read_value (TestTypeNode *node, 2363 DBusTypeReader *reader, 2364 int seed) 2365 { 2366 #ifdef DBUS_HAVE_INT64 2367 /* also used for uint64 */ 2368 dbus_int64_t v; 2369 2370 check_expected_type (reader, node->klass->typecode); 2371 2372 _dbus_type_reader_read_basic (reader, 2373 (dbus_int64_t*) &v); 2374 2375 _dbus_assert (v == int64_from_seed (seed)); 2376 2377 return TRUE; 2378 #else 2379 return TRUE; 2380 #endif 2381 } 2382 2383 static dbus_bool_t 2384 int64_set_value (TestTypeNode *node, 2385 DBusTypeReader *reader, 2386 DBusTypeReader *realign_root, 2387 int seed) 2388 { 2389 #ifdef DBUS_HAVE_INT64 2390 /* also used for uint64 */ 2391 dbus_int64_t v; 2392 2393 v = int64_from_seed (seed); 2394 2395 return _dbus_type_reader_set_basic (reader, 2396 &v, 2397 realign_root); 2398 #else 2399 return TRUE; 2400 #endif 2401 } 2402 2403 #define MAX_SAMPLE_STRING_LEN 10 2404 static void 2405 string_from_seed (char *buf, 2406 int len, 2407 int seed) 2408 { 2409 int i; 2410 unsigned char v; 2411 2412 _dbus_assert (len < MAX_SAMPLE_STRING_LEN); 2413 2414 /* vary the length slightly, though we also have multiple string 2415 * value types for this, varying it here tests the set_value code 2416 */ 2417 switch (seed % 3) 2418 { 2419 case 1: 2420 len += 2; 2421 break; 2422 case 2: 2423 len -= 2; 2424 break; 2425 } 2426 if (len < 0) 2427 len = 0; 2428 2429 v = (unsigned char) ('A' + seed); 2430 2431 i = 0; 2432 while (i < len) 2433 { 2434 if (v < 'A' || v > 'z') 2435 v = 'A'; 2436 2437 buf[i] = v; 2438 2439 v += 1; 2440 ++i; 2441 } 2442 2443 buf[i] = '\0'; 2444 } 2445 2446 static dbus_bool_t 2447 string_write_value (TestTypeNode *node, 2448 DataBlock *block, 2449 DBusTypeWriter *writer, 2450 int seed) 2451 { 2452 char buf[MAX_SAMPLE_STRING_LEN + 1]=""; 2453 const char *v_string = buf; 2454 2455 2456 string_from_seed (buf, node->klass->subclass_detail, 2457 seed); 2458 2459 return _dbus_type_writer_write_basic (writer, 2460 node->klass->typecode, 2461 &v_string); 2462 } 2463 2464 static dbus_bool_t 2465 string_read_value (TestTypeNode *node, 2466 DBusTypeReader *reader, 2467 int seed) 2468 { 2469 const char *v; 2470 char buf[MAX_SAMPLE_STRING_LEN + 1]; 2471 v = buf; 2472 2473 check_expected_type (reader, node->klass->typecode); 2474 2475 _dbus_type_reader_read_basic (reader, 2476 (const char **) &v); 2477 2478 string_from_seed (buf, node->klass->subclass_detail, 2479 seed); 2480 2481 if (strcmp (buf, v) != 0) 2482 { 2483 _dbus_warn ("read string '%s' expected '%s'\n", 2484 v, buf); 2485 _dbus_assert_not_reached ("test failed"); 2486 } 2487 2488 return TRUE; 2489 } 2490 2491 static dbus_bool_t 2492 string_set_value (TestTypeNode *node, 2493 DBusTypeReader *reader, 2494 DBusTypeReader *realign_root, 2495 int seed) 2496 { 2497 char buf[MAX_SAMPLE_STRING_LEN + 1]; 2498 const char *v_string = buf; 2499 2500 string_from_seed (buf, node->klass->subclass_detail, 2501 seed); 2502 2503 #if RECURSIVE_MARSHAL_WRITE_TRACE 2504 { 2505 const char *old; 2506 _dbus_type_reader_read_basic (reader, &old); 2507 _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n", 2508 v_string, strlen (v_string), old, strlen (old)); 2509 } 2510 #endif 2511 2512 return _dbus_type_reader_set_basic (reader, 2513 &v_string, 2514 realign_root); 2515 } 2516 2517 #define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2)) 2518 2519 static dbus_bool_t 2520 bool_write_value (TestTypeNode *node, 2521 DataBlock *block, 2522 DBusTypeWriter *writer, 2523 int seed) 2524 { 2525 dbus_bool_t v; 2526 2527 v = BOOL_FROM_SEED (seed); 2528 2529 return _dbus_type_writer_write_basic (writer, 2530 node->klass->typecode, 2531 &v); 2532 } 2533 2534 static dbus_bool_t 2535 bool_read_value (TestTypeNode *node, 2536 DBusTypeReader *reader, 2537 int seed) 2538 { 2539 dbus_bool_t v; 2540 2541 check_expected_type (reader, node->klass->typecode); 2542 2543 _dbus_type_reader_read_basic (reader, 2544 (unsigned char*) &v); 2545 2546 _dbus_assert (v == BOOL_FROM_SEED (seed)); 2547 2548 return TRUE; 2549 } 2550 2551 static dbus_bool_t 2552 bool_set_value (TestTypeNode *node, 2553 DBusTypeReader *reader, 2554 DBusTypeReader *realign_root, 2555 int seed) 2556 { 2557 dbus_bool_t v; 2558 2559 v = BOOL_FROM_SEED (seed); 2560 2561 return _dbus_type_reader_set_basic (reader, 2562 &v, 2563 realign_root); 2564 } 2565 2566 #define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed)) 2567 2568 static dbus_bool_t 2569 byte_write_value (TestTypeNode *node, 2570 DataBlock *block, 2571 DBusTypeWriter *writer, 2572 int seed) 2573 { 2574 unsigned char v; 2575 2576 v = BYTE_FROM_SEED (seed); 2577 2578 return _dbus_type_writer_write_basic (writer, 2579 node->klass->typecode, 2580 &v); 2581 } 2582 2583 static dbus_bool_t 2584 byte_read_value (TestTypeNode *node, 2585 DBusTypeReader *reader, 2586 int seed) 2587 { 2588 unsigned char v; 2589 2590 check_expected_type (reader, node->klass->typecode); 2591 2592 _dbus_type_reader_read_basic (reader, 2593 (unsigned char*) &v); 2594 2595 _dbus_assert (v == BYTE_FROM_SEED (seed)); 2596 2597 return TRUE; 2598 } 2599 2600 2601 static dbus_bool_t 2602 byte_set_value (TestTypeNode *node, 2603 DBusTypeReader *reader, 2604 DBusTypeReader *realign_root, 2605 int seed) 2606 { 2607 unsigned char v; 2608 2609 v = BYTE_FROM_SEED (seed); 2610 2611 return _dbus_type_reader_set_basic (reader, 2612 &v, 2613 realign_root); 2614 } 2615 2616 static double 2617 double_from_seed (int seed) 2618 { 2619 return SAMPLE_INT32 * (double) seed + 0.3; 2620 } 2621 2622 static dbus_bool_t 2623 double_write_value (TestTypeNode *node, 2624 DataBlock *block, 2625 DBusTypeWriter *writer, 2626 int seed) 2627 { 2628 double v; 2629 2630 v = double_from_seed (seed); 2631 2632 return _dbus_type_writer_write_basic (writer, 2633 node->klass->typecode, 2634 &v); 2635 } 2636 2637 static dbus_bool_t 2638 double_read_value (TestTypeNode *node, 2639 DBusTypeReader *reader, 2640 int seed) 2641 { 2642 double v; 2643 double expected; 2644 2645 check_expected_type (reader, node->klass->typecode); 2646 2647 _dbus_type_reader_read_basic (reader, 2648 (double*) &v); 2649 2650 expected = double_from_seed (seed); 2651 2652 if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected)) 2653 { 2654 #ifdef DBUS_INT64_PRINTF_MODIFIER 2655 _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", 2656 expected, v, 2657 *(dbus_uint64_t*)(char*)&expected, 2658 *(dbus_uint64_t*)(char*)&v); 2659 #endif 2660 _dbus_assert_not_reached ("test failed"); 2661 } 2662 2663 return TRUE; 2664 } 2665 2666 static dbus_bool_t 2667 double_set_value (TestTypeNode *node, 2668 DBusTypeReader *reader, 2669 DBusTypeReader *realign_root, 2670 int seed) 2671 { 2672 double v; 2673 2674 v = double_from_seed (seed); 2675 2676 return _dbus_type_reader_set_basic (reader, 2677 &v, 2678 realign_root); 2679 } 2680 2681 #define MAX_SAMPLE_OBJECT_PATH_LEN 10 2682 static void 2683 object_path_from_seed (char *buf, 2684 int seed) 2685 { 2686 int i; 2687 unsigned char v; 2688 int len; 2689 2690 len = seed % 9; 2691 _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN); 2692 2693 v = (unsigned char) ('A' + seed); 2694 2695 if (len < 2) 2696 { 2697 buf[0] = '/'; 2698 i = 1; 2699 } 2700 else 2701 { 2702 i = 0; 2703 while (i + 1 < len) 2704 { 2705 if (v < 'A' || v > 'z') 2706 v = 'A'; 2707 2708 buf[i] = '/'; 2709 ++i; 2710 buf[i] = v; 2711 ++i; 2712 2713 v += 1; 2714 } 2715 } 2716 2717 buf[i] = '\0'; 2718 } 2719 2720 static dbus_bool_t 2721 object_path_write_value (TestTypeNode *node, 2722 DataBlock *block, 2723 DBusTypeWriter *writer, 2724 int seed) 2725 { 2726 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 2727 const char *v_string = buf; 2728 2729 object_path_from_seed (buf, seed); 2730 2731 return _dbus_type_writer_write_basic (writer, 2732 node->klass->typecode, 2733 &v_string); 2734 } 2735 2736 static dbus_bool_t 2737 object_path_read_value (TestTypeNode *node, 2738 DBusTypeReader *reader, 2739 int seed) 2740 { 2741 const char *v; 2742 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 2743 2744 check_expected_type (reader, node->klass->typecode); 2745 2746 _dbus_type_reader_read_basic (reader, 2747 (const char **) &v); 2748 2749 object_path_from_seed (buf, seed); 2750 2751 if (strcmp (buf, v) != 0) 2752 { 2753 _dbus_warn ("read object path '%s' expected '%s'\n", 2754 v, buf); 2755 _dbus_assert_not_reached ("test failed"); 2756 } 2757 2758 return TRUE; 2759 } 2760 2761 static dbus_bool_t 2762 object_path_set_value (TestTypeNode *node, 2763 DBusTypeReader *reader, 2764 DBusTypeReader *realign_root, 2765 int seed) 2766 { 2767 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 2768 const char *v_string = buf; 2769 2770 object_path_from_seed (buf, seed); 2771 2772 return _dbus_type_reader_set_basic (reader, 2773 &v_string, 2774 realign_root); 2775 } 2776 2777 #define MAX_SAMPLE_SIGNATURE_LEN 10 2778 static void 2779 signature_from_seed (char *buf, 2780 int seed) 2781 { 2782 /* try to avoid ascending, descending, or alternating length to help find bugs */ 2783 const char *sample_signatures[] = { 2784 "asax" 2785 "", 2786 "asau(xxxx)", 2787 "x", 2788 "ai", 2789 "a(ii)" 2790 }; 2791 2792 strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]); 2793 } 2794 2795 static dbus_bool_t 2796 signature_write_value (TestTypeNode *node, 2797 DataBlock *block, 2798 DBusTypeWriter *writer, 2799 int seed) 2800 { 2801 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 2802 const char *v_string = buf; 2803 2804 signature_from_seed (buf, seed); 2805 2806 return _dbus_type_writer_write_basic (writer, 2807 node->klass->typecode, 2808 &v_string); 2809 } 2810 2811 static dbus_bool_t 2812 signature_read_value (TestTypeNode *node, 2813 DBusTypeReader *reader, 2814 int seed) 2815 { 2816 const char *v; 2817 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 2818 2819 check_expected_type (reader, node->klass->typecode); 2820 2821 _dbus_type_reader_read_basic (reader, 2822 (const char **) &v); 2823 2824 signature_from_seed (buf, seed); 2825 2826 if (strcmp (buf, v) != 0) 2827 { 2828 _dbus_warn ("read signature value '%s' expected '%s'\n", 2829 v, buf); 2830 _dbus_assert_not_reached ("test failed"); 2831 } 2832 2833 return TRUE; 2834 } 2835 2836 2837 static dbus_bool_t 2838 signature_set_value (TestTypeNode *node, 2839 DBusTypeReader *reader, 2840 DBusTypeReader *realign_root, 2841 int seed) 2842 { 2843 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 2844 const char *v_string = buf; 2845 2846 signature_from_seed (buf, seed); 2847 2848 return _dbus_type_reader_set_basic (reader, 2849 &v_string, 2850 realign_root); 2851 } 2852 2853 static dbus_bool_t 2854 struct_write_value (TestTypeNode *node, 2855 DataBlock *block, 2856 DBusTypeWriter *writer, 2857 int seed) 2858 { 2859 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 2860 DataBlockState saved; 2861 DBusTypeWriter sub; 2862 int i; 2863 int n_copies; 2864 2865 n_copies = node->klass->subclass_detail; 2866 2867 _dbus_assert (container->children != NULL); 2868 2869 data_block_save (block, &saved); 2870 2871 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT, 2872 NULL, 0, 2873 &sub)) 2874 return FALSE; 2875 2876 i = 0; 2877 while (i < n_copies) 2878 { 2879 DBusList *link; 2880 2881 link = _dbus_list_get_first_link (&container->children); 2882 while (link != NULL) 2883 { 2884 TestTypeNode *child = link->data; 2885 DBusList *next = _dbus_list_get_next_link (&container->children, link); 2886 2887 if (!node_write_value (child, block, &sub, seed + i)) 2888 { 2889 data_block_restore (block, &saved); 2890 return FALSE; 2891 } 2892 2893 link = next; 2894 } 2895 2896 ++i; 2897 } 2898 2899 if (!_dbus_type_writer_unrecurse (writer, &sub)) 2900 { 2901 data_block_restore (block, &saved); 2902 return FALSE; 2903 } 2904 2905 return TRUE; 2906 } 2907 2908 static dbus_bool_t 2909 struct_read_or_set_value (TestTypeNode *node, 2910 DBusTypeReader *reader, 2911 DBusTypeReader *realign_root, 2912 int seed) 2913 { 2914 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 2915 DBusTypeReader sub; 2916 int i; 2917 int n_copies; 2918 2919 n_copies = node->klass->subclass_detail; 2920 2921 check_expected_type (reader, DBUS_TYPE_STRUCT); 2922 2923 _dbus_type_reader_recurse (reader, &sub); 2924 2925 i = 0; 2926 while (i < n_copies) 2927 { 2928 DBusList *link; 2929 2930 link = _dbus_list_get_first_link (&container->children); 2931 while (link != NULL) 2932 { 2933 TestTypeNode *child = link->data; 2934 DBusList *next = _dbus_list_get_next_link (&container->children, link); 2935 2936 if (realign_root == NULL) 2937 { 2938 if (!node_read_value (child, &sub, seed + i)) 2939 return FALSE; 2940 } 2941 else 2942 { 2943 if (!node_set_value (child, &sub, realign_root, seed + i)) 2944 return FALSE; 2945 } 2946 2947 if (i == (n_copies - 1) && next == NULL) 2948 NEXT_EXPECTING_FALSE (&sub); 2949 else 2950 NEXT_EXPECTING_TRUE (&sub); 2951 2952 link = next; 2953 } 2954 2955 ++i; 2956 } 2957 2958 return TRUE; 2959 } 2960 2961 static dbus_bool_t 2962 struct_read_value (TestTypeNode *node, 2963 DBusTypeReader *reader, 2964 int seed) 2965 { 2966 return struct_read_or_set_value (node, reader, NULL, seed); 2967 } 2968 2969 static dbus_bool_t 2970 struct_set_value (TestTypeNode *node, 2971 DBusTypeReader *reader, 2972 DBusTypeReader *realign_root, 2973 int seed) 2974 { 2975 return struct_read_or_set_value (node, reader, realign_root, seed); 2976 } 2977 2978 static dbus_bool_t 2979 struct_build_signature (TestTypeNode *node, 2980 DBusString *str) 2981 { 2982 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 2983 int i; 2984 int orig_len; 2985 int n_copies; 2986 2987 n_copies = node->klass->subclass_detail; 2988 2989 orig_len = _dbus_string_get_length (str); 2990 2991 if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR)) 2992 goto oom; 2993 2994 i = 0; 2995 while (i < n_copies) 2996 { 2997 DBusList *link; 2998 2999 link = _dbus_list_get_first_link (&container->children); 3000 while (link != NULL) 3001 { 3002 TestTypeNode *child = link->data; 3003 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3004 3005 if (!node_build_signature (child, str)) 3006 goto oom; 3007 3008 link = next; 3009 } 3010 3011 ++i; 3012 } 3013 3014 if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR)) 3015 goto oom; 3016 3017 return TRUE; 3018 3019 oom: 3020 _dbus_string_set_length (str, orig_len); 3021 return FALSE; 3022 } 3023 3024 static dbus_bool_t 3025 array_write_value (TestTypeNode *node, 3026 DataBlock *block, 3027 DBusTypeWriter *writer, 3028 int seed) 3029 { 3030 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3031 DataBlockState saved; 3032 DBusTypeWriter sub; 3033 DBusString element_signature; 3034 int i; 3035 int n_copies; 3036 int element_type; 3037 TestTypeNode *child; 3038 3039 n_copies = node->klass->subclass_detail; 3040 3041 _dbus_assert (container->children != NULL); 3042 3043 data_block_save (block, &saved); 3044 3045 if (!_dbus_string_init (&element_signature)) 3046 return FALSE; 3047 3048 child = _dbus_list_get_first (&container->children); 3049 3050 if (!node_build_signature (child, 3051 &element_signature)) 3052 goto oom; 3053 3054 element_type = _dbus_first_type_in_signature (&element_signature, 0); 3055 3056 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, 3057 &element_signature, 0, 3058 &sub)) 3059 goto oom; 3060 3061 if (arrays_write_fixed_in_blocks && 3062 dbus_type_is_fixed (element_type) && 3063 child->klass->write_multi) 3064 { 3065 if (!node_write_multi (child, block, &sub, seed, n_copies)) 3066 goto oom; 3067 } 3068 else 3069 { 3070 i = 0; 3071 while (i < n_copies) 3072 { 3073 DBusList *link; 3074 3075 link = _dbus_list_get_first_link (&container->children); 3076 while (link != NULL) 3077 { 3078 TestTypeNode *child = link->data; 3079 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3080 3081 if (!node_write_value (child, block, &sub, seed + i)) 3082 goto oom; 3083 3084 link = next; 3085 } 3086 3087 ++i; 3088 } 3089 } 3090 3091 if (!_dbus_type_writer_unrecurse (writer, &sub)) 3092 goto oom; 3093 3094 _dbus_string_free (&element_signature); 3095 return TRUE; 3096 3097 oom: 3098 data_block_restore (block, &saved); 3099 _dbus_string_free (&element_signature); 3100 return FALSE; 3101 } 3102 3103 static dbus_bool_t 3104 array_read_or_set_value (TestTypeNode *node, 3105 DBusTypeReader *reader, 3106 DBusTypeReader *realign_root, 3107 int seed) 3108 { 3109 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3110 DBusTypeReader sub; 3111 int i; 3112 int n_copies; 3113 TestTypeNode *child; 3114 3115 n_copies = node->klass->subclass_detail; 3116 3117 check_expected_type (reader, DBUS_TYPE_ARRAY); 3118 3119 child = _dbus_list_get_first (&container->children); 3120 3121 if (n_copies > 0) 3122 { 3123 _dbus_type_reader_recurse (reader, &sub); 3124 3125 if (realign_root == NULL && arrays_write_fixed_in_blocks && 3126 dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) && 3127 child->klass->read_multi) 3128 { 3129 if (!node_read_multi (child, &sub, seed, n_copies)) 3130 return FALSE; 3131 } 3132 else 3133 { 3134 i = 0; 3135 while (i < n_copies) 3136 { 3137 DBusList *link; 3138 3139 link = _dbus_list_get_first_link (&container->children); 3140 while (link != NULL) 3141 { 3142 TestTypeNode *child = link->data; 3143 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3144 3145 _dbus_assert (child->klass->typecode == 3146 _dbus_type_reader_get_element_type (reader)); 3147 3148 if (realign_root == NULL) 3149 { 3150 if (!node_read_value (child, &sub, seed + i)) 3151 return FALSE; 3152 } 3153 else 3154 { 3155 if (!node_set_value (child, &sub, realign_root, seed + i)) 3156 return FALSE; 3157 } 3158 3159 if (i == (n_copies - 1) && next == NULL) 3160 NEXT_EXPECTING_FALSE (&sub); 3161 else 3162 NEXT_EXPECTING_TRUE (&sub); 3163 3164 link = next; 3165 } 3166 3167 ++i; 3168 } 3169 } 3170 } 3171 3172 return TRUE; 3173 } 3174 3175 static dbus_bool_t 3176 array_read_value (TestTypeNode *node, 3177 DBusTypeReader *reader, 3178 int seed) 3179 { 3180 return array_read_or_set_value (node, reader, NULL, seed); 3181 } 3182 3183 static dbus_bool_t 3184 array_set_value (TestTypeNode *node, 3185 DBusTypeReader *reader, 3186 DBusTypeReader *realign_root, 3187 int seed) 3188 { 3189 return array_read_or_set_value (node, reader, realign_root, seed); 3190 } 3191 3192 static dbus_bool_t 3193 array_build_signature (TestTypeNode *node, 3194 DBusString *str) 3195 { 3196 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3197 int orig_len; 3198 3199 orig_len = _dbus_string_get_length (str); 3200 3201 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) 3202 goto oom; 3203 3204 if (!node_build_signature (_dbus_list_get_first (&container->children), 3205 str)) 3206 goto oom; 3207 3208 return TRUE; 3209 3210 oom: 3211 _dbus_string_set_length (str, orig_len); 3212 return FALSE; 3213 } 3214 3215 /* 10 is random just to add another seed that we use in the suite */ 3216 #define VARIANT_SEED 10 3217 3218 static dbus_bool_t 3219 variant_write_value (TestTypeNode *node, 3220 DataBlock *block, 3221 DBusTypeWriter *writer, 3222 int seed) 3223 { 3224 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3225 DataBlockState saved; 3226 DBusTypeWriter sub; 3227 DBusString content_signature; 3228 TestTypeNode *child; 3229 3230 _dbus_assert (container->children != NULL); 3231 _dbus_assert (_dbus_list_length_is_one (&container->children)); 3232 3233 child = _dbus_list_get_first (&container->children); 3234 3235 data_block_save (block, &saved); 3236 3237 if (!_dbus_string_init (&content_signature)) 3238 return FALSE; 3239 3240 if (!node_build_signature (child, 3241 &content_signature)) 3242 goto oom; 3243 3244 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT, 3245 &content_signature, 0, 3246 &sub)) 3247 goto oom; 3248 3249 if (!node_write_value (child, block, &sub, seed + VARIANT_SEED)) 3250 goto oom; 3251 3252 if (!_dbus_type_writer_unrecurse (writer, &sub)) 3253 goto oom; 3254 3255 _dbus_string_free (&content_signature); 3256 return TRUE; 3257 3258 oom: 3259 data_block_restore (block, &saved); 3260 _dbus_string_free (&content_signature); 3261 return FALSE; 3262 } 3263 3264 static dbus_bool_t 3265 variant_read_or_set_value (TestTypeNode *node, 3266 DBusTypeReader *reader, 3267 DBusTypeReader *realign_root, 3268 int seed) 3269 { 3270 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3271 DBusTypeReader sub; 3272 TestTypeNode *child; 3273 3274 _dbus_assert (container->children != NULL); 3275 _dbus_assert (_dbus_list_length_is_one (&container->children)); 3276 3277 child = _dbus_list_get_first (&container->children); 3278 3279 check_expected_type (reader, DBUS_TYPE_VARIANT); 3280 3281 _dbus_type_reader_recurse (reader, &sub); 3282 3283 if (realign_root == NULL) 3284 { 3285 if (!node_read_value (child, &sub, seed + VARIANT_SEED)) 3286 return FALSE; 3287 } 3288 else 3289 { 3290 if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED)) 3291 return FALSE; 3292 } 3293 3294 NEXT_EXPECTING_FALSE (&sub); 3295 3296 return TRUE; 3297 } 3298 3299 static dbus_bool_t 3300 variant_read_value (TestTypeNode *node, 3301 DBusTypeReader *reader, 3302 int seed) 3303 { 3304 return variant_read_or_set_value (node, reader, NULL, seed); 3305 } 3306 3307 static dbus_bool_t 3308 variant_set_value (TestTypeNode *node, 3309 DBusTypeReader *reader, 3310 DBusTypeReader *realign_root, 3311 int seed) 3312 { 3313 return variant_read_or_set_value (node, reader, realign_root, seed); 3314 } 3315 3316 static dbus_bool_t 3317 dict_write_value (TestTypeNode *node, 3318 DataBlock *block, 3319 DBusTypeWriter *writer, 3320 int seed) 3321 { 3322 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3323 DataBlockState saved; 3324 DBusTypeWriter sub; 3325 DBusString entry_value_signature; 3326 DBusString dict_entry_signature; 3327 int i; 3328 int n_entries; 3329 int entry_value_type; 3330 TestTypeNode *child; 3331 3332 n_entries = node->klass->subclass_detail; 3333 3334 _dbus_assert (container->children != NULL); 3335 3336 data_block_save (block, &saved); 3337 3338 if (!_dbus_string_init (&entry_value_signature)) 3339 return FALSE; 3340 3341 if (!_dbus_string_init (&dict_entry_signature)) 3342 { 3343 _dbus_string_free (&entry_value_signature); 3344 return FALSE; 3345 } 3346 3347 child = _dbus_list_get_first (&container->children); 3348 3349 if (!node_build_signature (child, 3350 &entry_value_signature)) 3351 goto oom; 3352 3353 if (!_dbus_string_append (&dict_entry_signature, 3354 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 3355 DBUS_TYPE_INT32_AS_STRING)) 3356 goto oom; 3357 3358 if (!_dbus_string_copy (&entry_value_signature, 0, 3359 &dict_entry_signature, 3360 _dbus_string_get_length (&dict_entry_signature))) 3361 goto oom; 3362 3363 if (!_dbus_string_append_byte (&dict_entry_signature, 3364 DBUS_DICT_ENTRY_END_CHAR)) 3365 goto oom; 3366 3367 entry_value_type = _dbus_first_type_in_signature (&entry_value_signature, 0); 3368 3369 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, 3370 &dict_entry_signature, 0, 3371 &sub)) 3372 goto oom; 3373 3374 i = 0; 3375 while (i < n_entries) 3376 { 3377 DBusTypeWriter entry_sub; 3378 dbus_int32_t key; 3379 3380 if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY, 3381 NULL, 0, 3382 &entry_sub)) 3383 goto oom; 3384 3385 key = int32_from_seed (seed + i); 3386 3387 if (!_dbus_type_writer_write_basic (&entry_sub, 3388 DBUS_TYPE_INT32, 3389 &key)) 3390 goto oom; 3391 3392 if (!node_write_value (child, block, &entry_sub, seed + i)) 3393 goto oom; 3394 3395 if (!_dbus_type_writer_unrecurse (&sub, &entry_sub)) 3396 goto oom; 3397 3398 ++i; 3399 } 3400 3401 if (!_dbus_type_writer_unrecurse (writer, &sub)) 3402 goto oom; 3403 3404 _dbus_string_free (&entry_value_signature); 3405 _dbus_string_free (&dict_entry_signature); 3406 return TRUE; 3407 3408 oom: 3409 data_block_restore (block, &saved); 3410 _dbus_string_free (&entry_value_signature); 3411 _dbus_string_free (&dict_entry_signature); 3412 return FALSE; 3413 } 3414 3415 static dbus_bool_t 3416 dict_read_or_set_value (TestTypeNode *node, 3417 DBusTypeReader *reader, 3418 DBusTypeReader *realign_root, 3419 int seed) 3420 { 3421 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3422 DBusTypeReader sub; 3423 int i; 3424 int n_entries; 3425 TestTypeNode *child; 3426 3427 n_entries = node->klass->subclass_detail; 3428 3429 check_expected_type (reader, DBUS_TYPE_ARRAY); 3430 3431 child = _dbus_list_get_first (&container->children); 3432 3433 if (n_entries > 0) 3434 { 3435 _dbus_type_reader_recurse (reader, &sub); 3436 3437 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); 3438 3439 i = 0; 3440 while (i < n_entries) 3441 { 3442 DBusTypeReader entry_sub; 3443 3444 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); 3445 3446 _dbus_type_reader_recurse (&sub, &entry_sub); 3447 3448 if (realign_root == NULL) 3449 { 3450 dbus_int32_t v; 3451 3452 check_expected_type (&entry_sub, DBUS_TYPE_INT32); 3453 3454 _dbus_type_reader_read_basic (&entry_sub, 3455 (dbus_int32_t*) &v); 3456 3457 _dbus_assert (v == int32_from_seed (seed + i)); 3458 3459 NEXT_EXPECTING_TRUE (&entry_sub); 3460 3461 if (!node_read_value (child, &entry_sub, seed + i)) 3462 return FALSE; 3463 3464 NEXT_EXPECTING_FALSE (&entry_sub); 3465 } 3466 else 3467 { 3468 dbus_int32_t v; 3469 3470 v = int32_from_seed (seed + i); 3471 3472 if (!_dbus_type_reader_set_basic (&entry_sub, 3473 &v, 3474 realign_root)) 3475 return FALSE; 3476 3477 NEXT_EXPECTING_TRUE (&entry_sub); 3478 3479 if (!node_set_value (child, &entry_sub, realign_root, seed + i)) 3480 return FALSE; 3481 3482 NEXT_EXPECTING_FALSE (&entry_sub); 3483 } 3484 3485 if (i == (n_entries - 1)) 3486 NEXT_EXPECTING_FALSE (&sub); 3487 else 3488 NEXT_EXPECTING_TRUE (&sub); 3489 3490 ++i; 3491 } 3492 } 3493 3494 return TRUE; 3495 } 3496 3497 static dbus_bool_t 3498 dict_read_value (TestTypeNode *node, 3499 DBusTypeReader *reader, 3500 int seed) 3501 { 3502 return dict_read_or_set_value (node, reader, NULL, seed); 3503 } 3504 3505 static dbus_bool_t 3506 dict_set_value (TestTypeNode *node, 3507 DBusTypeReader *reader, 3508 DBusTypeReader *realign_root, 3509 int seed) 3510 { 3511 return dict_read_or_set_value (node, reader, realign_root, seed); 3512 } 3513 3514 static dbus_bool_t 3515 dict_build_signature (TestTypeNode *node, 3516 DBusString *str) 3517 { 3518 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3519 int orig_len; 3520 3521 orig_len = _dbus_string_get_length (str); 3522 3523 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) 3524 goto oom; 3525 3526 if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING)) 3527 goto oom; 3528 3529 if (!node_build_signature (_dbus_list_get_first (&container->children), 3530 str)) 3531 goto oom; 3532 3533 if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR)) 3534 goto oom; 3535 3536 return TRUE; 3537 3538 oom: 3539 _dbus_string_set_length (str, orig_len); 3540 return FALSE; 3541 } 3542 3543 static void 3544 container_destroy (TestTypeNode *node) 3545 { 3546 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3547 DBusList *link; 3548 3549 link = _dbus_list_get_first_link (&container->children); 3550 while (link != NULL) 3551 { 3552 TestTypeNode *child = link->data; 3553 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3554 3555 node_destroy (child); 3556 3557 _dbus_list_free_link (link); 3558 3559 link = next; 3560 } 3561 } 3562 3563 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 3564 3565 #endif /* DBUS_BUILD_TESTS */ 3566