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 34static void 35basic_value_zero (DBusBasicValue *value) 36{ 37 38#ifdef DBUS_HAVE_INT64 39 value->u64 = 0; 40#else 41 value->eight.first32 = 0; 42 value->eight.second32 = 0; 43#endif 44} 45 46static dbus_bool_t 47basic_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->eight.first32 == rhs->eight.first32 && 63 lhs->eight.second32 == rhs->eight.second32; 64#endif 65 } 66} 67 68static dbus_bool_t 69equal_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 */ 116dbus_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 148typedef struct 149{ 150 int byte_order; 151 int initial_offset; 152 DBusString signature; 153 DBusString body; 154} DataBlock; 155 156typedef 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 166static dbus_bool_t 167data_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 198static void 199data_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 206static void 207data_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 218static void 219data_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 256static void 257data_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 265static void 266data_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 280static void 281data_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 302static void 303real_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 342typedef struct TestTypeNode TestTypeNode; 343typedef struct TestTypeNodeClass TestTypeNodeClass; 344typedef struct TestTypeNodeContainer TestTypeNodeContainer; 345typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass; 346 347struct TestTypeNode 348{ 349 const TestTypeNodeClass *klass; 350}; 351 352struct TestTypeNodeContainer 353{ 354 TestTypeNode base; 355 DBusList *children; 356}; 357 358struct 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 393struct 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 */ 403static dbus_bool_t int16_write_value (TestTypeNode *node, 404 DataBlock *block, 405 DBusTypeWriter *writer, 406 int seed); 407static dbus_bool_t int16_read_value (TestTypeNode *node, 408 DBusTypeReader *reader, 409 int seed); 410static dbus_bool_t int16_set_value (TestTypeNode *node, 411 DBusTypeReader *reader, 412 DBusTypeReader *realign_root, 413 int seed); 414static dbus_bool_t int16_write_multi (TestTypeNode *node, 415 DataBlock *block, 416 DBusTypeWriter *writer, 417 int seed, 418 int count); 419static dbus_bool_t int16_read_multi (TestTypeNode *node, 420 DBusTypeReader *reader, 421 int seed, 422 int count); 423static dbus_bool_t int32_write_value (TestTypeNode *node, 424 DataBlock *block, 425 DBusTypeWriter *writer, 426 int seed); 427static dbus_bool_t int32_read_value (TestTypeNode *node, 428 DBusTypeReader *reader, 429 int seed); 430static dbus_bool_t int32_set_value (TestTypeNode *node, 431 DBusTypeReader *reader, 432 DBusTypeReader *realign_root, 433 int seed); 434static dbus_bool_t int32_write_multi (TestTypeNode *node, 435 DataBlock *block, 436 DBusTypeWriter *writer, 437 int seed, 438 int count); 439static dbus_bool_t int32_read_multi (TestTypeNode *node, 440 DBusTypeReader *reader, 441 int seed, 442 int count); 443static dbus_bool_t int64_write_value (TestTypeNode *node, 444 DataBlock *block, 445 DBusTypeWriter *writer, 446 int seed); 447static dbus_bool_t int64_read_value (TestTypeNode *node, 448 DBusTypeReader *reader, 449 int seed); 450static dbus_bool_t int64_set_value (TestTypeNode *node, 451 DBusTypeReader *reader, 452 DBusTypeReader *realign_root, 453 int seed); 454static dbus_bool_t string_write_value (TestTypeNode *node, 455 DataBlock *block, 456 DBusTypeWriter *writer, 457 int seed); 458static dbus_bool_t string_read_value (TestTypeNode *node, 459 DBusTypeReader *reader, 460 int seed); 461static dbus_bool_t string_set_value (TestTypeNode *node, 462 DBusTypeReader *reader, 463 DBusTypeReader *realign_root, 464 int seed); 465static dbus_bool_t bool_write_value (TestTypeNode *node, 466 DataBlock *block, 467 DBusTypeWriter *writer, 468 int seed); 469static dbus_bool_t bool_read_value (TestTypeNode *node, 470 DBusTypeReader *reader, 471 int seed); 472static dbus_bool_t bool_set_value (TestTypeNode *node, 473 DBusTypeReader *reader, 474 DBusTypeReader *realign_root, 475 int seed); 476static dbus_bool_t byte_write_value (TestTypeNode *node, 477 DataBlock *block, 478 DBusTypeWriter *writer, 479 int seed); 480static dbus_bool_t byte_read_value (TestTypeNode *node, 481 DBusTypeReader *reader, 482 int seed); 483static dbus_bool_t byte_set_value (TestTypeNode *node, 484 DBusTypeReader *reader, 485 DBusTypeReader *realign_root, 486 int seed); 487static dbus_bool_t double_write_value (TestTypeNode *node, 488 DataBlock *block, 489 DBusTypeWriter *writer, 490 int seed); 491static dbus_bool_t double_read_value (TestTypeNode *node, 492 DBusTypeReader *reader, 493 int seed); 494static dbus_bool_t double_set_value (TestTypeNode *node, 495 DBusTypeReader *reader, 496 DBusTypeReader *realign_root, 497 int seed); 498static dbus_bool_t object_path_write_value (TestTypeNode *node, 499 DataBlock *block, 500 DBusTypeWriter *writer, 501 int seed); 502static dbus_bool_t object_path_read_value (TestTypeNode *node, 503 DBusTypeReader *reader, 504 int seed); 505static dbus_bool_t object_path_set_value (TestTypeNode *node, 506 DBusTypeReader *reader, 507 DBusTypeReader *realign_root, 508 int seed); 509static dbus_bool_t signature_write_value (TestTypeNode *node, 510 DataBlock *block, 511 DBusTypeWriter *writer, 512 int seed); 513static dbus_bool_t signature_read_value (TestTypeNode *node, 514 DBusTypeReader *reader, 515 int seed); 516static dbus_bool_t signature_set_value (TestTypeNode *node, 517 DBusTypeReader *reader, 518 DBusTypeReader *realign_root, 519 int seed); 520static dbus_bool_t struct_write_value (TestTypeNode *node, 521 DataBlock *block, 522 DBusTypeWriter *writer, 523 int seed); 524static dbus_bool_t struct_read_value (TestTypeNode *node, 525 DBusTypeReader *reader, 526 int seed); 527static dbus_bool_t struct_set_value (TestTypeNode *node, 528 DBusTypeReader *reader, 529 DBusTypeReader *realign_root, 530 int seed); 531static dbus_bool_t struct_build_signature (TestTypeNode *node, 532 DBusString *str); 533static dbus_bool_t dict_write_value (TestTypeNode *node, 534 DataBlock *block, 535 DBusTypeWriter *writer, 536 int seed); 537static dbus_bool_t dict_read_value (TestTypeNode *node, 538 DBusTypeReader *reader, 539 int seed); 540static dbus_bool_t dict_set_value (TestTypeNode *node, 541 DBusTypeReader *reader, 542 DBusTypeReader *realign_root, 543 int seed); 544static dbus_bool_t dict_build_signature (TestTypeNode *node, 545 DBusString *str); 546static dbus_bool_t array_write_value (TestTypeNode *node, 547 DataBlock *block, 548 DBusTypeWriter *writer, 549 int seed); 550static dbus_bool_t array_read_value (TestTypeNode *node, 551 DBusTypeReader *reader, 552 int seed); 553static dbus_bool_t array_set_value (TestTypeNode *node, 554 DBusTypeReader *reader, 555 DBusTypeReader *realign_root, 556 int seed); 557static dbus_bool_t array_build_signature (TestTypeNode *node, 558 DBusString *str); 559static dbus_bool_t variant_write_value (TestTypeNode *node, 560 DataBlock *block, 561 DBusTypeWriter *writer, 562 int seed); 563static dbus_bool_t variant_read_value (TestTypeNode *node, 564 DBusTypeReader *reader, 565 int seed); 566static dbus_bool_t variant_set_value (TestTypeNode *node, 567 DBusTypeReader *reader, 568 DBusTypeReader *realign_root, 569 int seed); 570static void container_destroy (TestTypeNode *node); 571 572 573 574static 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 588static 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 602static 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 616static 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 630static 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 644static 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 658static 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 672static 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" */ 687static 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) */ 702static 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 716static 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 730static 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 744static 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 758static 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 772static 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 786static 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 800static 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 814static 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 828static dbus_bool_t arrays_write_fixed_in_blocks = FALSE; 829 830static 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 844static 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 858static 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 872static 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 886static 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 900static const TestTypeNodeClass* const 901basic_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 920static const TestTypeNodeClass* const 921container_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 935static TestTypeNode* 936node_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 958static void 959node_destroy (TestTypeNode *node) 960{ 961 if (node->klass->destroy) 962 (* node->klass->destroy) (node); 963 dbus_free (node); 964} 965 966static dbus_bool_t 967node_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 984static dbus_bool_t 985node_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 */ 1001static dbus_bool_t 1002node_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 1013static dbus_bool_t 1014node_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 1023static dbus_bool_t 1024node_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 1037static dbus_bool_t 1038node_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 1057static dbus_bool_t 1058node_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 1071static int n_iterations_completed_total = 0; 1072static int n_iterations_completed_this_test = 0; 1073static int n_iterations_expected_this_test = 0; 1074 1075typedef struct 1076{ 1077 const DBusString *signature; 1078 DataBlock *block; 1079 int type_offset; 1080 TestTypeNode **nodes; 1081 int n_nodes; 1082} NodeIterationData; 1083 1084static dbus_bool_t 1085run_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 1147static dbus_bool_t 1148run_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 1216static dbus_bool_t 1217run_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 1274static dbus_bool_t 1275run_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 1366static dbus_bool_t 1367run_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 1461static void 1462run_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 1496static void 1497run_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 1550static TestTypeNode* 1551value_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 1595static void 1596build_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 1646dbus_bool_t 1647dbus_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 1676static void 1677make_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 1710static void 1711start_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 1722static void 1723make_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 if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL || 1928 atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1) 1929 { 1930 fprintf (stderr, "skipping remaining marshal-recursive tests, " 1931 "run with DBUS_TEST_SLOW=1 (or more) to enable\n"); 1932 goto out; 1933 } 1934 1935 start_next_test ("Each container of each container of each value %d iterations\n", 1936 N_CONTAINERS * N_CONTAINERS * N_VALUES); 1937 for (i = 0; i < N_CONTAINERS; i++) 1938 { 1939 const TestTypeNodeClass *outer_container_klass = container_nodes[i]; 1940 TestTypeNode *outer_container = node_new (outer_container_klass); 1941 1942 for (j = 0; j < N_CONTAINERS; j++) 1943 { 1944 TestTypeNode *child; 1945 const TestTypeNodeClass *inner_container_klass = container_nodes[j]; 1946 TestTypeNode *inner_container = node_new (inner_container_klass); 1947 1948 node_append_child (outer_container, inner_container); 1949 1950 m = 0; 1951 while ((child = value_generator (&m))) 1952 { 1953 node_append_child (inner_container, child); 1954 1955 run_test_nodes (&outer_container, 1); 1956 1957 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children); 1958 node_destroy (child); 1959 } 1960 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children); 1961 node_destroy (inner_container); 1962 } 1963 node_destroy (outer_container); 1964 } 1965 1966 start_next_test ("Each container of each container of each container of each value %d iterations\n", 1967 N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES); 1968 for (i = 0; i < N_CONTAINERS; i++) 1969 { 1970 const TestTypeNodeClass *outer_container_klass = container_nodes[i]; 1971 TestTypeNode *outer_container = node_new (outer_container_klass); 1972 1973 for (j = 0; j < N_CONTAINERS; j++) 1974 { 1975 const TestTypeNodeClass *inner_container_klass = container_nodes[j]; 1976 TestTypeNode *inner_container = node_new (inner_container_klass); 1977 1978 node_append_child (outer_container, inner_container); 1979 1980 for (k = 0; k < N_CONTAINERS; k++) 1981 { 1982 TestTypeNode *child; 1983 const TestTypeNodeClass *center_container_klass = container_nodes[k]; 1984 TestTypeNode *center_container = node_new (center_container_klass); 1985 1986 node_append_child (inner_container, center_container); 1987 1988 m = 0; 1989 while ((child = value_generator (&m))) 1990 { 1991 node_append_child (center_container, child); 1992 1993 run_test_nodes (&outer_container, 1); 1994 1995 _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children); 1996 node_destroy (child); 1997 } 1998 _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children); 1999 node_destroy (center_container); 2000 } 2001 _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children); 2002 node_destroy (inner_container); 2003 } 2004 node_destroy (outer_container); 2005 } 2006 2007 /* This one takes a really long time (10 minutes on a Core2), so only enable 2008 * it if you're really sure */ 2009 if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2) 2010 { 2011 fprintf (stderr, "skipping really slow marshal-recursive test, " 2012 "run with DBUS_TEST_SLOW=2 (or more) to enable\n"); 2013 goto out; 2014 } 2015 2016 start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n", 2017 N_VALUES * N_VALUES * N_VALUES); 2018 { 2019 TestTypeNode *nodes[3]; 2020 2021 i = 0; 2022 while ((nodes[0] = value_generator (&i))) 2023 { 2024 j = 0; 2025 while ((nodes[1] = value_generator (&j))) 2026 { 2027 k = 0; 2028 while ((nodes[2] = value_generator (&k))) 2029 { 2030 run_test_nodes (nodes, 3); 2031 2032 node_destroy (nodes[2]); 2033 } 2034 node_destroy (nodes[1]); 2035 } 2036 node_destroy (nodes[0]); 2037 } 2038 } 2039 2040out: 2041 fprintf (stderr, "%d total iterations of recursive marshaling tests\n", 2042 n_iterations_completed_total); 2043 fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n", 2044 MAX_INITIAL_OFFSET); 2045 fprintf (stderr, "out of memory handling %s tested\n", 2046 TEST_OOM_HANDLING ? "was" : "was not"); 2047} 2048 2049dbus_bool_t 2050_dbus_marshal_recursive_test (void) 2051{ 2052 make_and_run_test_nodes (); 2053 2054 return TRUE; 2055} 2056 2057/* 2058 * 2059 * 2060 * Implementations of each type node class 2061 * 2062 * 2063 * 2064 */ 2065#define MAX_MULTI_COUNT 5 2066 2067#define SAMPLE_INT16 1234 2068#define SAMPLE_INT16_ALTERNATE 6785 2069static dbus_int16_t 2070int16_from_seed (int seed) 2071{ 2072 /* Generate an integer value that's predictable from seed. We could 2073 * just use seed itself, but that would only ever touch one byte of 2074 * the int so would miss some kinds of bug. 2075 */ 2076 dbus_int16_t v; 2077 2078 v = 42; /* just to quiet compiler afaik */ 2079 switch (seed % 5) 2080 { 2081 case 0: 2082 v = SAMPLE_INT16; 2083 break; 2084 case 1: 2085 v = SAMPLE_INT16_ALTERNATE; 2086 break; 2087 case 2: 2088 v = -1; 2089 break; 2090 case 3: 2091 v = _DBUS_INT16_MAX; 2092 break; 2093 case 4: 2094 v = 1; 2095 break; 2096 } 2097 2098 if (seed > 1) 2099 v *= seed; /* wraps around eventually, which is fine */ 2100 2101 return v; 2102} 2103 2104static dbus_bool_t 2105int16_write_value (TestTypeNode *node, 2106 DataBlock *block, 2107 DBusTypeWriter *writer, 2108 int seed) 2109{ 2110 /* also used for uint16 */ 2111 dbus_int16_t v; 2112 2113 v = int16_from_seed (seed); 2114 2115 return _dbus_type_writer_write_basic (writer, 2116 node->klass->typecode, 2117 &v); 2118} 2119 2120static dbus_bool_t 2121int16_read_value (TestTypeNode *node, 2122 DBusTypeReader *reader, 2123 int seed) 2124{ 2125 /* also used for uint16 */ 2126 dbus_int16_t v; 2127 2128 check_expected_type (reader, node->klass->typecode); 2129 2130 _dbus_type_reader_read_basic (reader, 2131 (dbus_int16_t*) &v); 2132 2133 _dbus_assert (v == int16_from_seed (seed)); 2134 2135 return TRUE; 2136} 2137 2138static dbus_bool_t 2139int16_set_value (TestTypeNode *node, 2140 DBusTypeReader *reader, 2141 DBusTypeReader *realign_root, 2142 int seed) 2143{ 2144 /* also used for uint16 */ 2145 dbus_int16_t v; 2146 2147 v = int16_from_seed (seed); 2148 2149 return _dbus_type_reader_set_basic (reader, 2150 &v, 2151 realign_root); 2152} 2153 2154static dbus_bool_t 2155int16_write_multi (TestTypeNode *node, 2156 DataBlock *block, 2157 DBusTypeWriter *writer, 2158 int seed, 2159 int count) 2160{ 2161 /* also used for uint16 */ 2162 dbus_int16_t values[MAX_MULTI_COUNT]; 2163 dbus_int16_t *v_ARRAY_INT16 = values; 2164 int i; 2165 2166 for (i = 0; i < count; ++i) 2167 values[i] = int16_from_seed (seed + i); 2168 2169 return _dbus_type_writer_write_fixed_multi (writer, 2170 node->klass->typecode, 2171 &v_ARRAY_INT16, count); 2172} 2173 2174static dbus_bool_t 2175int16_read_multi (TestTypeNode *node, 2176 DBusTypeReader *reader, 2177 int seed, 2178 int count) 2179{ 2180 /* also used for uint16 */ 2181 dbus_int16_t *values; 2182 int n_elements; 2183 int i; 2184 2185 check_expected_type (reader, node->klass->typecode); 2186 2187 _dbus_type_reader_read_fixed_multi (reader, 2188 &values, 2189 &n_elements); 2190 2191 if (n_elements != count) 2192 _dbus_warn ("got %d elements expected %d\n", n_elements, count); 2193 _dbus_assert (n_elements == count); 2194 2195 for (i = 0; i < count; i++) 2196 _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order, 2197 (const unsigned char*)values + (i * 2))) == 2198 int16_from_seed (seed + i)); 2199 2200 return TRUE; 2201} 2202 2203 2204#define SAMPLE_INT32 12345678 2205#define SAMPLE_INT32_ALTERNATE 53781429 2206static dbus_int32_t 2207int32_from_seed (int seed) 2208{ 2209 /* Generate an integer value that's predictable from seed. We could 2210 * just use seed itself, but that would only ever touch one byte of 2211 * the int so would miss some kinds of bug. 2212 */ 2213 dbus_int32_t v; 2214 2215 v = 42; /* just to quiet compiler afaik */ 2216 switch (seed % 5) 2217 { 2218 case 0: 2219 v = SAMPLE_INT32; 2220 break; 2221 case 1: 2222 v = SAMPLE_INT32_ALTERNATE; 2223 break; 2224 case 2: 2225 v = -1; 2226 break; 2227 case 3: 2228 v = _DBUS_INT_MAX; 2229 break; 2230 case 4: 2231 v = 1; 2232 break; 2233 } 2234 2235 if (seed > 1) 2236 v *= seed; /* wraps around eventually, which is fine */ 2237 2238 return v; 2239} 2240 2241static dbus_bool_t 2242int32_write_value (TestTypeNode *node, 2243 DataBlock *block, 2244 DBusTypeWriter *writer, 2245 int seed) 2246{ 2247 /* also used for uint32 */ 2248 dbus_int32_t v; 2249 2250 v = int32_from_seed (seed); 2251 2252 return _dbus_type_writer_write_basic (writer, 2253 node->klass->typecode, 2254 &v); 2255} 2256 2257static dbus_bool_t 2258int32_read_value (TestTypeNode *node, 2259 DBusTypeReader *reader, 2260 int seed) 2261{ 2262 /* also used for uint32 */ 2263 dbus_int32_t v; 2264 2265 check_expected_type (reader, node->klass->typecode); 2266 2267 _dbus_type_reader_read_basic (reader, 2268 (dbus_int32_t*) &v); 2269 2270 _dbus_assert (v == int32_from_seed (seed)); 2271 2272 return TRUE; 2273} 2274 2275static dbus_bool_t 2276int32_set_value (TestTypeNode *node, 2277 DBusTypeReader *reader, 2278 DBusTypeReader *realign_root, 2279 int seed) 2280{ 2281 /* also used for uint32 */ 2282 dbus_int32_t v; 2283 2284 v = int32_from_seed (seed); 2285 2286 return _dbus_type_reader_set_basic (reader, 2287 &v, 2288 realign_root); 2289} 2290 2291static dbus_bool_t 2292int32_write_multi (TestTypeNode *node, 2293 DataBlock *block, 2294 DBusTypeWriter *writer, 2295 int seed, 2296 int count) 2297{ 2298 /* also used for uint32 */ 2299 dbus_int32_t values[MAX_MULTI_COUNT]; 2300 dbus_int32_t *v_ARRAY_INT32 = values; 2301 int i; 2302 2303 for (i = 0; i < count; ++i) 2304 values[i] = int32_from_seed (seed + i); 2305 2306 return _dbus_type_writer_write_fixed_multi (writer, 2307 node->klass->typecode, 2308 &v_ARRAY_INT32, count); 2309} 2310 2311static dbus_bool_t 2312int32_read_multi (TestTypeNode *node, 2313 DBusTypeReader *reader, 2314 int seed, 2315 int count) 2316{ 2317 /* also used for uint32 */ 2318 dbus_int32_t *values; 2319 int n_elements; 2320 int i; 2321 2322 check_expected_type (reader, node->klass->typecode); 2323 2324 _dbus_type_reader_read_fixed_multi (reader, 2325 &values, 2326 &n_elements); 2327 2328 if (n_elements != count) 2329 _dbus_warn ("got %d elements expected %d\n", n_elements, count); 2330 _dbus_assert (n_elements == count); 2331 2332 for (i = 0; i < count; i++) 2333 _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order, 2334 (const unsigned char*)values + (i * 4))) == 2335 int32_from_seed (seed + i)); 2336 2337 return TRUE; 2338} 2339 2340#ifdef DBUS_HAVE_INT64 2341static dbus_int64_t 2342int64_from_seed (int seed) 2343{ 2344 dbus_int32_t v32; 2345 dbus_int64_t v; 2346 2347 v32 = int32_from_seed (seed); 2348 2349 v = - (dbus_int32_t) ~ v32; 2350 v |= (((dbus_int64_t)v32) << 32); 2351 2352 return v; 2353} 2354#endif 2355 2356static dbus_bool_t 2357int64_write_value (TestTypeNode *node, 2358 DataBlock *block, 2359 DBusTypeWriter *writer, 2360 int seed) 2361{ 2362#ifdef DBUS_HAVE_INT64 2363 /* also used for uint64 */ 2364 dbus_int64_t v; 2365 2366 v = int64_from_seed (seed); 2367 2368 return _dbus_type_writer_write_basic (writer, 2369 node->klass->typecode, 2370 &v); 2371#else 2372 return TRUE; 2373#endif 2374} 2375 2376static dbus_bool_t 2377int64_read_value (TestTypeNode *node, 2378 DBusTypeReader *reader, 2379 int seed) 2380{ 2381#ifdef DBUS_HAVE_INT64 2382 /* also used for uint64 */ 2383 dbus_int64_t v; 2384 2385 check_expected_type (reader, node->klass->typecode); 2386 2387 _dbus_type_reader_read_basic (reader, 2388 (dbus_int64_t*) &v); 2389 2390 _dbus_assert (v == int64_from_seed (seed)); 2391 2392 return TRUE; 2393#else 2394 return TRUE; 2395#endif 2396} 2397 2398static dbus_bool_t 2399int64_set_value (TestTypeNode *node, 2400 DBusTypeReader *reader, 2401 DBusTypeReader *realign_root, 2402 int seed) 2403{ 2404#ifdef DBUS_HAVE_INT64 2405 /* also used for uint64 */ 2406 dbus_int64_t v; 2407 2408 v = int64_from_seed (seed); 2409 2410 return _dbus_type_reader_set_basic (reader, 2411 &v, 2412 realign_root); 2413#else 2414 return TRUE; 2415#endif 2416} 2417 2418#define MAX_SAMPLE_STRING_LEN 10 2419static void 2420string_from_seed (char *buf, 2421 int len, 2422 int seed) 2423{ 2424 int i; 2425 unsigned char v; 2426 2427 _dbus_assert (len < MAX_SAMPLE_STRING_LEN); 2428 2429 /* vary the length slightly, though we also have multiple string 2430 * value types for this, varying it here tests the set_value code 2431 */ 2432 switch (seed % 3) 2433 { 2434 case 1: 2435 len += 2; 2436 break; 2437 case 2: 2438 len -= 2; 2439 break; 2440 } 2441 if (len < 0) 2442 len = 0; 2443 2444 v = (unsigned char) ('A' + seed); 2445 2446 i = 0; 2447 while (i < len) 2448 { 2449 if (v < 'A' || v > 'z') 2450 v = 'A'; 2451 2452 buf[i] = v; 2453 2454 v += 1; 2455 ++i; 2456 } 2457 2458 buf[i] = '\0'; 2459} 2460 2461static dbus_bool_t 2462string_write_value (TestTypeNode *node, 2463 DataBlock *block, 2464 DBusTypeWriter *writer, 2465 int seed) 2466{ 2467 char buf[MAX_SAMPLE_STRING_LEN + 1]=""; 2468 const char *v_string = buf; 2469 2470 2471 string_from_seed (buf, node->klass->subclass_detail, 2472 seed); 2473 2474 return _dbus_type_writer_write_basic (writer, 2475 node->klass->typecode, 2476 &v_string); 2477} 2478 2479static dbus_bool_t 2480string_read_value (TestTypeNode *node, 2481 DBusTypeReader *reader, 2482 int seed) 2483{ 2484 const char *v; 2485 char buf[MAX_SAMPLE_STRING_LEN + 1]; 2486 v = buf; 2487 2488 check_expected_type (reader, node->klass->typecode); 2489 2490 _dbus_type_reader_read_basic (reader, 2491 (const char **) &v); 2492 2493 string_from_seed (buf, node->klass->subclass_detail, 2494 seed); 2495 2496 if (strcmp (buf, v) != 0) 2497 { 2498 _dbus_warn ("read string '%s' expected '%s'\n", 2499 v, buf); 2500 _dbus_assert_not_reached ("test failed"); 2501 } 2502 2503 return TRUE; 2504} 2505 2506static dbus_bool_t 2507string_set_value (TestTypeNode *node, 2508 DBusTypeReader *reader, 2509 DBusTypeReader *realign_root, 2510 int seed) 2511{ 2512 char buf[MAX_SAMPLE_STRING_LEN + 1]; 2513 const char *v_string = buf; 2514 2515 string_from_seed (buf, node->klass->subclass_detail, 2516 seed); 2517 2518#if RECURSIVE_MARSHAL_WRITE_TRACE 2519 { 2520 const char *old; 2521 _dbus_type_reader_read_basic (reader, &old); 2522 _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n", 2523 v_string, strlen (v_string), old, strlen (old)); 2524 } 2525#endif 2526 2527 return _dbus_type_reader_set_basic (reader, 2528 &v_string, 2529 realign_root); 2530} 2531 2532#define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2)) 2533 2534static dbus_bool_t 2535bool_write_value (TestTypeNode *node, 2536 DataBlock *block, 2537 DBusTypeWriter *writer, 2538 int seed) 2539{ 2540 dbus_bool_t v; 2541 2542 v = BOOL_FROM_SEED (seed); 2543 2544 return _dbus_type_writer_write_basic (writer, 2545 node->klass->typecode, 2546 &v); 2547} 2548 2549static dbus_bool_t 2550bool_read_value (TestTypeNode *node, 2551 DBusTypeReader *reader, 2552 int seed) 2553{ 2554 dbus_bool_t v; 2555 2556 check_expected_type (reader, node->klass->typecode); 2557 2558 _dbus_type_reader_read_basic (reader, 2559 (unsigned char*) &v); 2560 2561 _dbus_assert (v == BOOL_FROM_SEED (seed)); 2562 2563 return TRUE; 2564} 2565 2566static dbus_bool_t 2567bool_set_value (TestTypeNode *node, 2568 DBusTypeReader *reader, 2569 DBusTypeReader *realign_root, 2570 int seed) 2571{ 2572 dbus_bool_t v; 2573 2574 v = BOOL_FROM_SEED (seed); 2575 2576 return _dbus_type_reader_set_basic (reader, 2577 &v, 2578 realign_root); 2579} 2580 2581#define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed)) 2582 2583static dbus_bool_t 2584byte_write_value (TestTypeNode *node, 2585 DataBlock *block, 2586 DBusTypeWriter *writer, 2587 int seed) 2588{ 2589 unsigned char v; 2590 2591 v = BYTE_FROM_SEED (seed); 2592 2593 return _dbus_type_writer_write_basic (writer, 2594 node->klass->typecode, 2595 &v); 2596} 2597 2598static dbus_bool_t 2599byte_read_value (TestTypeNode *node, 2600 DBusTypeReader *reader, 2601 int seed) 2602{ 2603 unsigned char v; 2604 2605 check_expected_type (reader, node->klass->typecode); 2606 2607 _dbus_type_reader_read_basic (reader, 2608 (unsigned char*) &v); 2609 2610 _dbus_assert (v == BYTE_FROM_SEED (seed)); 2611 2612 return TRUE; 2613} 2614 2615 2616static dbus_bool_t 2617byte_set_value (TestTypeNode *node, 2618 DBusTypeReader *reader, 2619 DBusTypeReader *realign_root, 2620 int seed) 2621{ 2622 unsigned char v; 2623 2624 v = BYTE_FROM_SEED (seed); 2625 2626 return _dbus_type_reader_set_basic (reader, 2627 &v, 2628 realign_root); 2629} 2630 2631static double 2632double_from_seed (int seed) 2633{ 2634 return SAMPLE_INT32 * (double) seed + 0.3; 2635} 2636 2637static dbus_bool_t 2638double_write_value (TestTypeNode *node, 2639 DataBlock *block, 2640 DBusTypeWriter *writer, 2641 int seed) 2642{ 2643 double v; 2644 2645 v = double_from_seed (seed); 2646 2647 return _dbus_type_writer_write_basic (writer, 2648 node->klass->typecode, 2649 &v); 2650} 2651 2652static dbus_bool_t 2653double_read_value (TestTypeNode *node, 2654 DBusTypeReader *reader, 2655 int seed) 2656{ 2657 double v; 2658 double expected; 2659 2660 check_expected_type (reader, node->klass->typecode); 2661 2662 _dbus_type_reader_read_basic (reader, 2663 (double*) &v); 2664 2665 expected = double_from_seed (seed); 2666 2667 if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected)) 2668 { 2669#ifdef DBUS_INT64_PRINTF_MODIFIER 2670 _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", 2671 expected, v, 2672 *(dbus_uint64_t*)(char*)&expected, 2673 *(dbus_uint64_t*)(char*)&v); 2674#endif 2675 _dbus_assert_not_reached ("test failed"); 2676 } 2677 2678 return TRUE; 2679} 2680 2681static dbus_bool_t 2682double_set_value (TestTypeNode *node, 2683 DBusTypeReader *reader, 2684 DBusTypeReader *realign_root, 2685 int seed) 2686{ 2687 double v; 2688 2689 v = double_from_seed (seed); 2690 2691 return _dbus_type_reader_set_basic (reader, 2692 &v, 2693 realign_root); 2694} 2695 2696#define MAX_SAMPLE_OBJECT_PATH_LEN 10 2697static void 2698object_path_from_seed (char *buf, 2699 int seed) 2700{ 2701 int i; 2702 unsigned char v; 2703 int len; 2704 2705 len = seed % 9; 2706 _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN); 2707 2708 v = (unsigned char) ('A' + seed); 2709 2710 if (len < 2) 2711 { 2712 buf[0] = '/'; 2713 i = 1; 2714 } 2715 else 2716 { 2717 i = 0; 2718 while (i + 1 < len) 2719 { 2720 if (v < 'A' || v > 'z') 2721 v = 'A'; 2722 2723 buf[i] = '/'; 2724 ++i; 2725 buf[i] = v; 2726 ++i; 2727 2728 v += 1; 2729 } 2730 } 2731 2732 buf[i] = '\0'; 2733} 2734 2735static dbus_bool_t 2736object_path_write_value (TestTypeNode *node, 2737 DataBlock *block, 2738 DBusTypeWriter *writer, 2739 int seed) 2740{ 2741 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 2742 const char *v_string = buf; 2743 2744 object_path_from_seed (buf, seed); 2745 2746 return _dbus_type_writer_write_basic (writer, 2747 node->klass->typecode, 2748 &v_string); 2749} 2750 2751static dbus_bool_t 2752object_path_read_value (TestTypeNode *node, 2753 DBusTypeReader *reader, 2754 int seed) 2755{ 2756 const char *v; 2757 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 2758 2759 check_expected_type (reader, node->klass->typecode); 2760 2761 _dbus_type_reader_read_basic (reader, 2762 (const char **) &v); 2763 2764 object_path_from_seed (buf, seed); 2765 2766 if (strcmp (buf, v) != 0) 2767 { 2768 _dbus_warn ("read object path '%s' expected '%s'\n", 2769 v, buf); 2770 _dbus_assert_not_reached ("test failed"); 2771 } 2772 2773 return TRUE; 2774} 2775 2776static dbus_bool_t 2777object_path_set_value (TestTypeNode *node, 2778 DBusTypeReader *reader, 2779 DBusTypeReader *realign_root, 2780 int seed) 2781{ 2782 char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1]; 2783 const char *v_string = buf; 2784 2785 object_path_from_seed (buf, seed); 2786 2787 return _dbus_type_reader_set_basic (reader, 2788 &v_string, 2789 realign_root); 2790} 2791 2792#define MAX_SAMPLE_SIGNATURE_LEN 10 2793static void 2794signature_from_seed (char *buf, 2795 int seed) 2796{ 2797 /* try to avoid ascending, descending, or alternating length to help find bugs */ 2798 const char *sample_signatures[] = { 2799 "asax" 2800 "", 2801 "asau(xxxx)", 2802 "x", 2803 "ai", 2804 "a(ii)" 2805 }; 2806 2807 strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]); 2808} 2809 2810static dbus_bool_t 2811signature_write_value (TestTypeNode *node, 2812 DataBlock *block, 2813 DBusTypeWriter *writer, 2814 int seed) 2815{ 2816 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 2817 const char *v_string = buf; 2818 2819 signature_from_seed (buf, seed); 2820 2821 return _dbus_type_writer_write_basic (writer, 2822 node->klass->typecode, 2823 &v_string); 2824} 2825 2826static dbus_bool_t 2827signature_read_value (TestTypeNode *node, 2828 DBusTypeReader *reader, 2829 int seed) 2830{ 2831 const char *v; 2832 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 2833 2834 check_expected_type (reader, node->klass->typecode); 2835 2836 _dbus_type_reader_read_basic (reader, 2837 (const char **) &v); 2838 2839 signature_from_seed (buf, seed); 2840 2841 if (strcmp (buf, v) != 0) 2842 { 2843 _dbus_warn ("read signature value '%s' expected '%s'\n", 2844 v, buf); 2845 _dbus_assert_not_reached ("test failed"); 2846 } 2847 2848 return TRUE; 2849} 2850 2851 2852static dbus_bool_t 2853signature_set_value (TestTypeNode *node, 2854 DBusTypeReader *reader, 2855 DBusTypeReader *realign_root, 2856 int seed) 2857{ 2858 char buf[MAX_SAMPLE_SIGNATURE_LEN + 1]; 2859 const char *v_string = buf; 2860 2861 signature_from_seed (buf, seed); 2862 2863 return _dbus_type_reader_set_basic (reader, 2864 &v_string, 2865 realign_root); 2866} 2867 2868static dbus_bool_t 2869struct_write_value (TestTypeNode *node, 2870 DataBlock *block, 2871 DBusTypeWriter *writer, 2872 int seed) 2873{ 2874 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 2875 DataBlockState saved; 2876 DBusTypeWriter sub; 2877 int i; 2878 int n_copies; 2879 2880 n_copies = node->klass->subclass_detail; 2881 2882 _dbus_assert (container->children != NULL); 2883 2884 data_block_save (block, &saved); 2885 2886 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT, 2887 NULL, 0, 2888 &sub)) 2889 return FALSE; 2890 2891 i = 0; 2892 while (i < n_copies) 2893 { 2894 DBusList *link; 2895 2896 link = _dbus_list_get_first_link (&container->children); 2897 while (link != NULL) 2898 { 2899 TestTypeNode *child = link->data; 2900 DBusList *next = _dbus_list_get_next_link (&container->children, link); 2901 2902 if (!node_write_value (child, block, &sub, seed + i)) 2903 { 2904 data_block_restore (block, &saved); 2905 return FALSE; 2906 } 2907 2908 link = next; 2909 } 2910 2911 ++i; 2912 } 2913 2914 if (!_dbus_type_writer_unrecurse (writer, &sub)) 2915 { 2916 data_block_restore (block, &saved); 2917 return FALSE; 2918 } 2919 2920 return TRUE; 2921} 2922 2923static dbus_bool_t 2924struct_read_or_set_value (TestTypeNode *node, 2925 DBusTypeReader *reader, 2926 DBusTypeReader *realign_root, 2927 int seed) 2928{ 2929 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 2930 DBusTypeReader sub; 2931 int i; 2932 int n_copies; 2933 2934 n_copies = node->klass->subclass_detail; 2935 2936 check_expected_type (reader, DBUS_TYPE_STRUCT); 2937 2938 _dbus_type_reader_recurse (reader, &sub); 2939 2940 i = 0; 2941 while (i < n_copies) 2942 { 2943 DBusList *link; 2944 2945 link = _dbus_list_get_first_link (&container->children); 2946 while (link != NULL) 2947 { 2948 TestTypeNode *child = link->data; 2949 DBusList *next = _dbus_list_get_next_link (&container->children, link); 2950 2951 if (realign_root == NULL) 2952 { 2953 if (!node_read_value (child, &sub, seed + i)) 2954 return FALSE; 2955 } 2956 else 2957 { 2958 if (!node_set_value (child, &sub, realign_root, seed + i)) 2959 return FALSE; 2960 } 2961 2962 if (i == (n_copies - 1) && next == NULL) 2963 NEXT_EXPECTING_FALSE (&sub); 2964 else 2965 NEXT_EXPECTING_TRUE (&sub); 2966 2967 link = next; 2968 } 2969 2970 ++i; 2971 } 2972 2973 return TRUE; 2974} 2975 2976static dbus_bool_t 2977struct_read_value (TestTypeNode *node, 2978 DBusTypeReader *reader, 2979 int seed) 2980{ 2981 return struct_read_or_set_value (node, reader, NULL, seed); 2982} 2983 2984static dbus_bool_t 2985struct_set_value (TestTypeNode *node, 2986 DBusTypeReader *reader, 2987 DBusTypeReader *realign_root, 2988 int seed) 2989{ 2990 return struct_read_or_set_value (node, reader, realign_root, seed); 2991} 2992 2993static dbus_bool_t 2994struct_build_signature (TestTypeNode *node, 2995 DBusString *str) 2996{ 2997 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 2998 int i; 2999 int orig_len; 3000 int n_copies; 3001 3002 n_copies = node->klass->subclass_detail; 3003 3004 orig_len = _dbus_string_get_length (str); 3005 3006 if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR)) 3007 goto oom; 3008 3009 i = 0; 3010 while (i < n_copies) 3011 { 3012 DBusList *link; 3013 3014 link = _dbus_list_get_first_link (&container->children); 3015 while (link != NULL) 3016 { 3017 TestTypeNode *child = link->data; 3018 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3019 3020 if (!node_build_signature (child, str)) 3021 goto oom; 3022 3023 link = next; 3024 } 3025 3026 ++i; 3027 } 3028 3029 if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR)) 3030 goto oom; 3031 3032 return TRUE; 3033 3034 oom: 3035 _dbus_string_set_length (str, orig_len); 3036 return FALSE; 3037} 3038 3039static dbus_bool_t 3040array_write_value (TestTypeNode *node, 3041 DataBlock *block, 3042 DBusTypeWriter *writer, 3043 int seed) 3044{ 3045 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3046 DataBlockState saved; 3047 DBusTypeWriter sub; 3048 DBusString element_signature; 3049 int i; 3050 int n_copies; 3051 int element_type; 3052 TestTypeNode *child; 3053 3054 n_copies = node->klass->subclass_detail; 3055 3056 _dbus_assert (container->children != NULL); 3057 3058 data_block_save (block, &saved); 3059 3060 if (!_dbus_string_init (&element_signature)) 3061 return FALSE; 3062 3063 child = _dbus_list_get_first (&container->children); 3064 3065 if (!node_build_signature (child, 3066 &element_signature)) 3067 goto oom; 3068 3069 element_type = _dbus_first_type_in_signature (&element_signature, 0); 3070 3071 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, 3072 &element_signature, 0, 3073 &sub)) 3074 goto oom; 3075 3076 if (arrays_write_fixed_in_blocks && 3077 dbus_type_is_fixed (element_type) && 3078 child->klass->write_multi) 3079 { 3080 if (!node_write_multi (child, block, &sub, seed, n_copies)) 3081 goto oom; 3082 } 3083 else 3084 { 3085 i = 0; 3086 while (i < n_copies) 3087 { 3088 DBusList *link; 3089 3090 link = _dbus_list_get_first_link (&container->children); 3091 while (link != NULL) 3092 { 3093 TestTypeNode *child = link->data; 3094 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3095 3096 if (!node_write_value (child, block, &sub, seed + i)) 3097 goto oom; 3098 3099 link = next; 3100 } 3101 3102 ++i; 3103 } 3104 } 3105 3106 if (!_dbus_type_writer_unrecurse (writer, &sub)) 3107 goto oom; 3108 3109 _dbus_string_free (&element_signature); 3110 return TRUE; 3111 3112 oom: 3113 data_block_restore (block, &saved); 3114 _dbus_string_free (&element_signature); 3115 return FALSE; 3116} 3117 3118static dbus_bool_t 3119array_read_or_set_value (TestTypeNode *node, 3120 DBusTypeReader *reader, 3121 DBusTypeReader *realign_root, 3122 int seed) 3123{ 3124 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3125 DBusTypeReader sub; 3126 int i; 3127 int n_copies; 3128 TestTypeNode *child; 3129 3130 n_copies = node->klass->subclass_detail; 3131 3132 check_expected_type (reader, DBUS_TYPE_ARRAY); 3133 3134 child = _dbus_list_get_first (&container->children); 3135 3136 if (n_copies > 0) 3137 { 3138 _dbus_type_reader_recurse (reader, &sub); 3139 3140 if (realign_root == NULL && arrays_write_fixed_in_blocks && 3141 dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) && 3142 child->klass->read_multi) 3143 { 3144 if (!node_read_multi (child, &sub, seed, n_copies)) 3145 return FALSE; 3146 } 3147 else 3148 { 3149 i = 0; 3150 while (i < n_copies) 3151 { 3152 DBusList *link; 3153 3154 link = _dbus_list_get_first_link (&container->children); 3155 while (link != NULL) 3156 { 3157 TestTypeNode *child = link->data; 3158 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3159 3160 _dbus_assert (child->klass->typecode == 3161 _dbus_type_reader_get_element_type (reader)); 3162 3163 if (realign_root == NULL) 3164 { 3165 if (!node_read_value (child, &sub, seed + i)) 3166 return FALSE; 3167 } 3168 else 3169 { 3170 if (!node_set_value (child, &sub, realign_root, seed + i)) 3171 return FALSE; 3172 } 3173 3174 if (i == (n_copies - 1) && next == NULL) 3175 NEXT_EXPECTING_FALSE (&sub); 3176 else 3177 NEXT_EXPECTING_TRUE (&sub); 3178 3179 link = next; 3180 } 3181 3182 ++i; 3183 } 3184 } 3185 } 3186 3187 return TRUE; 3188} 3189 3190static dbus_bool_t 3191array_read_value (TestTypeNode *node, 3192 DBusTypeReader *reader, 3193 int seed) 3194{ 3195 return array_read_or_set_value (node, reader, NULL, seed); 3196} 3197 3198static dbus_bool_t 3199array_set_value (TestTypeNode *node, 3200 DBusTypeReader *reader, 3201 DBusTypeReader *realign_root, 3202 int seed) 3203{ 3204 return array_read_or_set_value (node, reader, realign_root, seed); 3205} 3206 3207static dbus_bool_t 3208array_build_signature (TestTypeNode *node, 3209 DBusString *str) 3210{ 3211 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3212 int orig_len; 3213 3214 orig_len = _dbus_string_get_length (str); 3215 3216 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) 3217 goto oom; 3218 3219 if (!node_build_signature (_dbus_list_get_first (&container->children), 3220 str)) 3221 goto oom; 3222 3223 return TRUE; 3224 3225 oom: 3226 _dbus_string_set_length (str, orig_len); 3227 return FALSE; 3228} 3229 3230 /* 10 is random just to add another seed that we use in the suite */ 3231#define VARIANT_SEED 10 3232 3233static dbus_bool_t 3234variant_write_value (TestTypeNode *node, 3235 DataBlock *block, 3236 DBusTypeWriter *writer, 3237 int seed) 3238{ 3239 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3240 DataBlockState saved; 3241 DBusTypeWriter sub; 3242 DBusString content_signature; 3243 TestTypeNode *child; 3244 3245 _dbus_assert (container->children != NULL); 3246 _dbus_assert (_dbus_list_length_is_one (&container->children)); 3247 3248 child = _dbus_list_get_first (&container->children); 3249 3250 data_block_save (block, &saved); 3251 3252 if (!_dbus_string_init (&content_signature)) 3253 return FALSE; 3254 3255 if (!node_build_signature (child, 3256 &content_signature)) 3257 goto oom; 3258 3259 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT, 3260 &content_signature, 0, 3261 &sub)) 3262 goto oom; 3263 3264 if (!node_write_value (child, block, &sub, seed + VARIANT_SEED)) 3265 goto oom; 3266 3267 if (!_dbus_type_writer_unrecurse (writer, &sub)) 3268 goto oom; 3269 3270 _dbus_string_free (&content_signature); 3271 return TRUE; 3272 3273 oom: 3274 data_block_restore (block, &saved); 3275 _dbus_string_free (&content_signature); 3276 return FALSE; 3277} 3278 3279static dbus_bool_t 3280variant_read_or_set_value (TestTypeNode *node, 3281 DBusTypeReader *reader, 3282 DBusTypeReader *realign_root, 3283 int seed) 3284{ 3285 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3286 DBusTypeReader sub; 3287 TestTypeNode *child; 3288 3289 _dbus_assert (container->children != NULL); 3290 _dbus_assert (_dbus_list_length_is_one (&container->children)); 3291 3292 child = _dbus_list_get_first (&container->children); 3293 3294 check_expected_type (reader, DBUS_TYPE_VARIANT); 3295 3296 _dbus_type_reader_recurse (reader, &sub); 3297 3298 if (realign_root == NULL) 3299 { 3300 if (!node_read_value (child, &sub, seed + VARIANT_SEED)) 3301 return FALSE; 3302 } 3303 else 3304 { 3305 if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED)) 3306 return FALSE; 3307 } 3308 3309 NEXT_EXPECTING_FALSE (&sub); 3310 3311 return TRUE; 3312} 3313 3314static dbus_bool_t 3315variant_read_value (TestTypeNode *node, 3316 DBusTypeReader *reader, 3317 int seed) 3318{ 3319 return variant_read_or_set_value (node, reader, NULL, seed); 3320} 3321 3322static dbus_bool_t 3323variant_set_value (TestTypeNode *node, 3324 DBusTypeReader *reader, 3325 DBusTypeReader *realign_root, 3326 int seed) 3327{ 3328 return variant_read_or_set_value (node, reader, realign_root, seed); 3329} 3330 3331static dbus_bool_t 3332dict_write_value (TestTypeNode *node, 3333 DataBlock *block, 3334 DBusTypeWriter *writer, 3335 int seed) 3336{ 3337 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3338 DataBlockState saved; 3339 DBusTypeWriter sub; 3340 DBusString entry_value_signature; 3341 DBusString dict_entry_signature; 3342 int i; 3343 int n_entries; 3344 TestTypeNode *child; 3345 3346 n_entries = node->klass->subclass_detail; 3347 3348 _dbus_assert (container->children != NULL); 3349 3350 data_block_save (block, &saved); 3351 3352 if (!_dbus_string_init (&entry_value_signature)) 3353 return FALSE; 3354 3355 if (!_dbus_string_init (&dict_entry_signature)) 3356 { 3357 _dbus_string_free (&entry_value_signature); 3358 return FALSE; 3359 } 3360 3361 child = _dbus_list_get_first (&container->children); 3362 3363 if (!node_build_signature (child, 3364 &entry_value_signature)) 3365 goto oom; 3366 3367 if (!_dbus_string_append (&dict_entry_signature, 3368 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 3369 DBUS_TYPE_INT32_AS_STRING)) 3370 goto oom; 3371 3372 if (!_dbus_string_copy (&entry_value_signature, 0, 3373 &dict_entry_signature, 3374 _dbus_string_get_length (&dict_entry_signature))) 3375 goto oom; 3376 3377 if (!_dbus_string_append_byte (&dict_entry_signature, 3378 DBUS_DICT_ENTRY_END_CHAR)) 3379 goto oom; 3380 3381 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY, 3382 &dict_entry_signature, 0, 3383 &sub)) 3384 goto oom; 3385 3386 i = 0; 3387 while (i < n_entries) 3388 { 3389 DBusTypeWriter entry_sub; 3390 dbus_int32_t key; 3391 3392 if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY, 3393 NULL, 0, 3394 &entry_sub)) 3395 goto oom; 3396 3397 key = int32_from_seed (seed + i); 3398 3399 if (!_dbus_type_writer_write_basic (&entry_sub, 3400 DBUS_TYPE_INT32, 3401 &key)) 3402 goto oom; 3403 3404 if (!node_write_value (child, block, &entry_sub, seed + i)) 3405 goto oom; 3406 3407 if (!_dbus_type_writer_unrecurse (&sub, &entry_sub)) 3408 goto oom; 3409 3410 ++i; 3411 } 3412 3413 if (!_dbus_type_writer_unrecurse (writer, &sub)) 3414 goto oom; 3415 3416 _dbus_string_free (&entry_value_signature); 3417 _dbus_string_free (&dict_entry_signature); 3418 return TRUE; 3419 3420 oom: 3421 data_block_restore (block, &saved); 3422 _dbus_string_free (&entry_value_signature); 3423 _dbus_string_free (&dict_entry_signature); 3424 return FALSE; 3425} 3426 3427static dbus_bool_t 3428dict_read_or_set_value (TestTypeNode *node, 3429 DBusTypeReader *reader, 3430 DBusTypeReader *realign_root, 3431 int seed) 3432{ 3433 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3434 DBusTypeReader sub; 3435 int i; 3436 int n_entries; 3437 TestTypeNode *child; 3438 3439 n_entries = node->klass->subclass_detail; 3440 3441 check_expected_type (reader, DBUS_TYPE_ARRAY); 3442 3443 child = _dbus_list_get_first (&container->children); 3444 3445 if (n_entries > 0) 3446 { 3447 _dbus_type_reader_recurse (reader, &sub); 3448 3449 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); 3450 3451 i = 0; 3452 while (i < n_entries) 3453 { 3454 DBusTypeReader entry_sub; 3455 3456 check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY); 3457 3458 _dbus_type_reader_recurse (&sub, &entry_sub); 3459 3460 if (realign_root == NULL) 3461 { 3462 dbus_int32_t v; 3463 3464 check_expected_type (&entry_sub, DBUS_TYPE_INT32); 3465 3466 _dbus_type_reader_read_basic (&entry_sub, 3467 (dbus_int32_t*) &v); 3468 3469 _dbus_assert (v == int32_from_seed (seed + i)); 3470 3471 NEXT_EXPECTING_TRUE (&entry_sub); 3472 3473 if (!node_read_value (child, &entry_sub, seed + i)) 3474 return FALSE; 3475 3476 NEXT_EXPECTING_FALSE (&entry_sub); 3477 } 3478 else 3479 { 3480 dbus_int32_t v; 3481 3482 v = int32_from_seed (seed + i); 3483 3484 if (!_dbus_type_reader_set_basic (&entry_sub, 3485 &v, 3486 realign_root)) 3487 return FALSE; 3488 3489 NEXT_EXPECTING_TRUE (&entry_sub); 3490 3491 if (!node_set_value (child, &entry_sub, realign_root, seed + i)) 3492 return FALSE; 3493 3494 NEXT_EXPECTING_FALSE (&entry_sub); 3495 } 3496 3497 if (i == (n_entries - 1)) 3498 NEXT_EXPECTING_FALSE (&sub); 3499 else 3500 NEXT_EXPECTING_TRUE (&sub); 3501 3502 ++i; 3503 } 3504 } 3505 3506 return TRUE; 3507} 3508 3509static dbus_bool_t 3510dict_read_value (TestTypeNode *node, 3511 DBusTypeReader *reader, 3512 int seed) 3513{ 3514 return dict_read_or_set_value (node, reader, NULL, seed); 3515} 3516 3517static dbus_bool_t 3518dict_set_value (TestTypeNode *node, 3519 DBusTypeReader *reader, 3520 DBusTypeReader *realign_root, 3521 int seed) 3522{ 3523 return dict_read_or_set_value (node, reader, realign_root, seed); 3524} 3525 3526static dbus_bool_t 3527dict_build_signature (TestTypeNode *node, 3528 DBusString *str) 3529{ 3530 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3531 int orig_len; 3532 3533 orig_len = _dbus_string_get_length (str); 3534 3535 if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY)) 3536 goto oom; 3537 3538 if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING)) 3539 goto oom; 3540 3541 if (!node_build_signature (_dbus_list_get_first (&container->children), 3542 str)) 3543 goto oom; 3544 3545 if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR)) 3546 goto oom; 3547 3548 return TRUE; 3549 3550 oom: 3551 _dbus_string_set_length (str, orig_len); 3552 return FALSE; 3553} 3554 3555static void 3556container_destroy (TestTypeNode *node) 3557{ 3558 TestTypeNodeContainer *container = (TestTypeNodeContainer*) node; 3559 DBusList *link; 3560 3561 link = _dbus_list_get_first_link (&container->children); 3562 while (link != NULL) 3563 { 3564 TestTypeNode *child = link->data; 3565 DBusList *next = _dbus_list_get_next_link (&container->children, link); 3566 3567 node_destroy (child); 3568 3569 _dbus_list_free_link (link); 3570 3571 link = next; 3572 } 3573} 3574 3575#endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 3576 3577#endif /* DBUS_BUILD_TESTS */ 3578