1 #include <stdio.h> 2 #include <glib.h> 3 #include <stdlib.h> 4 5 /* Keep this in sync with gsequence.c !!! */ 6 typedef struct _GSequenceNode GSequenceNode; 7 8 struct _GSequence 9 { 10 GSequenceNode * end_node; 11 GDestroyNotify data_destroy_notify; 12 gboolean access_prohibited; 13 GSequence * real_sequence; 14 }; 15 16 struct _GSequenceNode 17 { 18 gint n_nodes; 19 GSequenceNode * parent; 20 GSequenceNode * left; 21 GSequenceNode * right; 22 gpointer data; 23 }; 24 25 static guint 26 get_priority (GSequenceNode *node) 27 { 28 guint key = GPOINTER_TO_UINT (node); 29 30 key = (key << 15) - key - 1; 31 key = key ^ (key >> 12); 32 key = key + (key << 2); 33 key = key ^ (key >> 4); 34 key = key + (key << 3) + (key << 11); 35 key = key ^ (key >> 16); 36 37 return key? key : 1; 38 } 39 40 static void 41 check_node (GSequenceNode *node) 42 { 43 if (node) 44 { 45 g_assert (node->parent != node); 46 if (node->parent) 47 g_assert (node->parent->left == node || node->parent->right == node); 48 g_assert (node->n_nodes == 1 + (node->left ? node->left->n_nodes : 0) + (node->right ? node->right->n_nodes : 0)); 49 if (node->left) 50 g_assert (get_priority (node) >= get_priority (node->left)); 51 if (node->right) 52 g_assert (get_priority (node) >= get_priority (node->right)); 53 check_node (node->left); 54 check_node (node->right); 55 } 56 } 57 58 void 59 g_sequence_check (GSequence *seq) 60 { 61 GSequenceNode *node = seq->end_node; 62 63 while (node->parent) 64 node = node->parent; 65 66 check_node (node); 67 68 while (node->right) 69 node = node->right; 70 71 g_assert (seq->end_node == node); 72 g_assert (node->data == seq); 73 74 } 75 76 77 enum { 78 NEW, FREE, GET_LENGTH, FOREACH, FOREACH_RANGE, SORT, SORT_ITER, 79 80 /* Getting iters */ 81 GET_BEGIN_ITER, GET_END_ITER, GET_ITER_AT_POS, APPEND, PREPEND, 82 INSERT_BEFORE, MOVE, SWAP, INSERT_SORTED, INSERT_SORTED_ITER, SORT_CHANGED, 83 SORT_CHANGED_ITER, REMOVE, REMOVE_RANGE, MOVE_RANGE, SEARCH, SEARCH_ITER, 84 85 /* dereferencing */ 86 GET, SET, 87 88 /* operations on GSequenceIter * */ 89 ITER_IS_BEGIN, ITER_IS_END, ITER_NEXT, ITER_PREV, ITER_GET_POSITION, 90 ITER_MOVE, ITER_GET_SEQUENCE, 91 92 /* search */ 93 ITER_COMPARE, RANGE_GET_MIDPOINT, 94 N_OPS 95 }; 96 97 typedef struct SequenceInfo 98 { 99 GQueue * queue; 100 GSequence * sequence; 101 int n_items; 102 } SequenceInfo; 103 104 typedef struct 105 { 106 SequenceInfo *seq; 107 int number; 108 } Item; 109 110 void g_sequence_check (GSequence *sequence); 111 112 static Item * 113 fix_pointer (gconstpointer data) 114 { 115 return (Item *)((char *)data - 1); 116 } 117 118 static Item * 119 get_item (GSequenceIter *iter) 120 { 121 return fix_pointer (g_sequence_get (iter)); 122 } 123 124 static void 125 check_integrity (SequenceInfo *info) 126 { 127 GList *list; 128 GSequenceIter *iter; 129 int i; 130 131 g_sequence_check (info->sequence); 132 133 if (g_sequence_get_length (info->sequence) != info->n_items) 134 g_print ("%d %d\n", 135 g_sequence_get_length (info->sequence), info->n_items); 136 g_assert (info->n_items == g_queue_get_length (info->queue)); 137 g_assert (g_sequence_get_length (info->sequence) == info->n_items); 138 139 iter = g_sequence_get_begin_iter (info->sequence); 140 list = info->queue->head; 141 i = 0; 142 while (iter != g_sequence_get_end_iter (info->sequence)) 143 { 144 Item *item; 145 g_assert (list->data == iter); 146 item = get_item (list->data); 147 g_assert (item->seq == info); 148 149 iter = g_sequence_iter_next (iter); 150 list = list->next; 151 i++; 152 } 153 154 g_assert (info->n_items == g_queue_get_length (info->queue)); 155 g_assert (g_sequence_get_length (info->sequence) == info->n_items); 156 } 157 158 static gpointer 159 new_item (SequenceInfo *seq) 160 { 161 Item *item = g_new (Item, 1); 162 seq->n_items++; 163 item->seq = seq; 164 item->number = g_random_int (); 165 166 /* There have been bugs in the past where the GSequence would 167 * dereference the user pointers. This will make sure such 168 * behavior causes crashes 169 */ 170 return ((char *)item + 1); 171 } 172 173 static void 174 free_item (gpointer data) 175 { 176 Item *item = fix_pointer (data); 177 item->seq->n_items--; 178 g_free (item); 179 } 180 181 static void 182 seq_foreach (gpointer data, 183 gpointer user_data) 184 { 185 Item *item = fix_pointer (data); 186 GList **link = user_data; 187 GSequenceIter *iter; 188 189 g_assert (*link != NULL); 190 191 iter = (*link)->data; 192 193 g_assert (get_item (iter) == item); 194 195 item->number = g_random_int(); 196 197 *link = (*link)->next; 198 } 199 200 static gint 201 compare_items (gconstpointer a, 202 gconstpointer b, 203 gpointer data) 204 { 205 const Item *item_a = fix_pointer (a); 206 const Item *item_b = fix_pointer (b); 207 208 if (item_a->number < item_b->number) 209 { 210 return -1; 211 } 212 else if (item_a->number == item_b->number) 213 { 214 /* Force an arbitrary order on the items 215 * We have to do this, since g_queue_insert_sorted() and 216 * g_sequence_insert_sorted() do not agree on the exact 217 * position the item is inserted if the new item is 218 * equal to an existing one. 219 */ 220 if (item_a < item_b) 221 return -1; 222 else if (item_a == item_b) 223 return 0; 224 else 225 return 1; 226 } 227 else 228 { 229 return 1; 230 } 231 } 232 233 static void 234 check_sorted (SequenceInfo *info) 235 { 236 GList *list; 237 int last; 238 GSequenceIter *last_iter; 239 240 check_integrity (info); 241 242 last = G_MININT; 243 last_iter = NULL; 244 for (list = info->queue->head; list != NULL; list = list->next) 245 { 246 GSequenceIter *iter = list->data; 247 Item *item = get_item (iter); 248 249 g_assert (item->number >= last); 250 /* Check that the ordering is the same as that of the queue, 251 * ie. that the sort is stable 252 */ 253 if (last_iter) 254 g_assert (iter == g_sequence_iter_next (last_iter)); 255 256 last = item->number; 257 last_iter = iter; 258 } 259 } 260 261 static gint 262 compare_iters (gconstpointer a, 263 gconstpointer b, 264 gpointer data) 265 { 266 GSequence *seq = data; 267 GSequenceIter *iter_a = (GSequenceIter *)a; 268 GSequenceIter *iter_b = (GSequenceIter *)b; 269 /* compare_items() will fix up the pointers */ 270 Item *item_a = g_sequence_get (iter_a); 271 Item *item_b = g_sequence_get (iter_b); 272 273 if (seq) 274 { 275 g_assert (g_sequence_iter_get_sequence (iter_a) == seq); 276 g_assert (g_sequence_iter_get_sequence (iter_b) == seq); 277 } 278 279 return compare_items (item_a, item_b, data); 280 } 281 282 /* A version of g_queue_link_index() that treats NULL as just 283 * beyond the queue 284 */ 285 static int 286 queue_link_index (SequenceInfo *seq, GList *link) 287 { 288 if (link) 289 return g_queue_link_index (seq->queue, link); 290 else 291 return g_queue_get_length (seq->queue); 292 } 293 294 static void 295 get_random_range (SequenceInfo *seq, 296 GSequenceIter **begin_iter, 297 GSequenceIter **end_iter, 298 GList **begin_link, 299 GList **end_link) 300 { 301 int length = g_queue_get_length (seq->queue); 302 int b = g_random_int_range (0, length + 1); 303 int e = g_random_int_range (b, length + 1); 304 305 g_assert (length == g_sequence_get_length (seq->sequence)); 306 307 if (begin_iter) 308 *begin_iter = g_sequence_get_iter_at_pos (seq->sequence, b); 309 if (end_iter) 310 *end_iter = g_sequence_get_iter_at_pos (seq->sequence, e); 311 if (begin_link) 312 *begin_link = g_queue_peek_nth_link (seq->queue, b); 313 if (end_link) 314 *end_link = g_queue_peek_nth_link (seq->queue, e); 315 if (begin_iter && begin_link) 316 { 317 g_assert ( 318 queue_link_index (seq, *begin_link) == 319 g_sequence_iter_get_position (*begin_iter)); 320 } 321 if (end_iter && end_link) 322 { 323 g_assert ( 324 queue_link_index (seq, *end_link) == 325 g_sequence_iter_get_position (*end_iter)); 326 } 327 } 328 329 static gint 330 get_random_position (SequenceInfo *seq) 331 { 332 int length = g_queue_get_length (seq->queue); 333 334 g_assert (length == g_sequence_get_length (seq->sequence)); 335 336 return g_random_int_range (-2, length + 5); 337 } 338 339 static GSequenceIter * 340 get_random_iter (SequenceInfo *seq, 341 GList **link) 342 { 343 GSequenceIter *iter; 344 int pos = get_random_position (seq); 345 if (link) 346 *link = g_queue_peek_nth_link (seq->queue, pos); 347 iter = g_sequence_get_iter_at_pos (seq->sequence, pos); 348 if (link) 349 g_assert (queue_link_index (seq, *link) == g_sequence_iter_get_position (iter)); 350 return iter; 351 } 352 353 static void 354 dump_info (SequenceInfo *seq) 355 { 356 #if 0 357 GSequenceIter *iter; 358 GList *list; 359 360 iter = g_sequence_get_begin_iter (seq->sequence); 361 list = seq->queue->head; 362 363 while (iter != g_sequence_get_end_iter (seq->sequence)) 364 { 365 Item *item = get_item (iter); 366 g_print ("%p %p %d\n", list->data, iter, item->number); 367 368 iter = g_sequence_iter_next (iter); 369 list = list->next; 370 } 371 #endif 372 } 373 374 /* A version of g_queue_insert_before() that appends if link is NULL */ 375 static void 376 queue_insert_before (SequenceInfo *seq, GList *link, gpointer data) 377 { 378 if (link) 379 g_queue_insert_before (seq->queue, link, data); 380 else 381 g_queue_push_tail (seq->queue, data); 382 } 383 384 static void 385 run_random_tests (guint32 seed) 386 { 387 #define N_ITERATIONS 60000 388 #define N_SEQUENCES 8 389 #define N_TIMES 24 390 391 SequenceInfo sequences[N_SEQUENCES]; 392 int k; 393 394 g_print (" seed: %u\n", seed); 395 396 g_random_set_seed (seed); 397 398 for (k = 0; k < N_SEQUENCES; ++k) 399 { 400 sequences[k].queue = g_queue_new (); 401 sequences[k].sequence = g_sequence_new (free_item); 402 sequences[k].n_items = 0; 403 } 404 405 #define RANDOM_SEQUENCE() &(sequences[g_random_int_range (0, N_SEQUENCES)]) 406 407 for (k = 0; k < N_ITERATIONS; ++k) 408 { 409 int i; 410 SequenceInfo *seq = RANDOM_SEQUENCE(); 411 int op = g_random_int_range (0, N_OPS); 412 413 #if 0 414 g_print ("%d on %p\n", op, seq); 415 #endif 416 417 switch (op) 418 { 419 case NEW: 420 case FREE: 421 { 422 g_queue_free (seq->queue); 423 g_sequence_free (seq->sequence); 424 425 g_assert (seq->n_items == 0); 426 427 seq->queue = g_queue_new (); 428 seq->sequence = g_sequence_new (free_item); 429 430 check_integrity (seq); 431 } 432 break; 433 case GET_LENGTH: 434 { 435 int slen = g_sequence_get_length (seq->sequence); 436 int qlen = g_queue_get_length (seq->queue); 437 438 g_assert (slen == qlen); 439 } 440 break; 441 case FOREACH: 442 { 443 GList *link = seq->queue->head; 444 g_sequence_foreach (seq->sequence, seq_foreach, &link); 445 g_assert (link == NULL); 446 } 447 break; 448 case FOREACH_RANGE: 449 { 450 GSequenceIter *begin_iter, *end_iter; 451 GList *begin_link, *end_link; 452 453 get_random_range (seq, &begin_iter, &end_iter, &begin_link, &end_link); 454 455 check_integrity (seq); 456 457 g_sequence_foreach_range (begin_iter, end_iter, seq_foreach, &begin_link); 458 459 g_assert (begin_link == end_link); 460 } 461 break; 462 case SORT: 463 { 464 dump_info (seq); 465 466 g_sequence_sort (seq->sequence, compare_items, NULL); 467 g_queue_sort (seq->queue, compare_iters, NULL); 468 469 check_sorted (seq); 470 471 dump_info (seq); 472 } 473 break; 474 case SORT_ITER: 475 { 476 check_integrity (seq); 477 g_sequence_sort_iter (seq->sequence, 478 (GSequenceIterCompareFunc)compare_iters, seq->sequence); 479 g_queue_sort (seq->queue, compare_iters, NULL); 480 check_sorted (seq); 481 } 482 break; 483 484 /* Getting iters */ 485 case GET_END_ITER: 486 case GET_BEGIN_ITER: 487 { 488 GSequenceIter *begin_iter; 489 GSequenceIter *end_iter; 490 GSequenceIter *penultimate_iter; 491 492 begin_iter = g_sequence_get_begin_iter (seq->sequence); 493 check_integrity (seq); 494 495 end_iter = g_sequence_get_end_iter (seq->sequence); 496 check_integrity (seq); 497 498 penultimate_iter = g_sequence_iter_prev (end_iter); 499 check_integrity (seq); 500 501 if (g_sequence_get_length (seq->sequence) > 0) 502 { 503 g_assert (seq->queue->head); 504 g_assert (seq->queue->head->data == begin_iter); 505 g_assert (seq->queue->tail); 506 g_assert (seq->queue->tail->data == penultimate_iter); 507 } 508 else 509 { 510 g_assert (penultimate_iter == end_iter); 511 g_assert (begin_iter == end_iter); 512 g_assert (penultimate_iter == begin_iter); 513 g_assert (seq->queue->head == NULL); 514 g_assert (seq->queue->tail == NULL); 515 } 516 } 517 break; 518 case GET_ITER_AT_POS: 519 { 520 int i; 521 522 g_assert (g_queue_get_length (seq->queue) == g_sequence_get_length (seq->sequence)); 523 524 for (i = 0; i < 10; ++i) 525 { 526 int pos = get_random_position (seq); 527 GSequenceIter *iter = g_sequence_get_iter_at_pos (seq->sequence, pos); 528 GList *link = g_queue_peek_nth_link (seq->queue, pos); 529 check_integrity (seq); 530 if (pos >= g_sequence_get_length (seq->sequence) || pos < 0) 531 { 532 g_assert (iter == g_sequence_get_end_iter (seq->sequence)); 533 g_assert (link == NULL); 534 } 535 else 536 { 537 g_assert (link); 538 g_assert (link->data == iter); 539 } 540 } 541 } 542 break; 543 case APPEND: 544 { 545 for (i = 0; i < 10; ++i) 546 { 547 GSequenceIter *iter = g_sequence_append (seq->sequence, new_item (seq)); 548 g_queue_push_tail (seq->queue, iter); 549 } 550 } 551 break; 552 case PREPEND: 553 { 554 for (i = 0; i < 10; ++i) 555 { 556 GSequenceIter *iter = g_sequence_prepend (seq->sequence, new_item (seq)); 557 g_queue_push_head (seq->queue, iter); 558 } 559 } 560 break; 561 case INSERT_BEFORE: 562 { 563 for (i = 0; i < 10; ++i) 564 { 565 GList *link; 566 GSequenceIter *iter = get_random_iter (seq, &link); 567 GSequenceIter *new_iter; 568 check_integrity (seq); 569 570 new_iter = g_sequence_insert_before (iter, new_item (seq)); 571 572 queue_insert_before (seq, link, new_iter); 573 } 574 } 575 break; 576 case MOVE: 577 { 578 GList *link1, *link2; 579 SequenceInfo *seq1 = RANDOM_SEQUENCE(); 580 SequenceInfo *seq2 = RANDOM_SEQUENCE(); 581 GSequenceIter *iter1 = get_random_iter (seq1, &link1); 582 GSequenceIter *iter2 = get_random_iter (seq2, &link2); 583 584 if (!g_sequence_iter_is_end (iter1)) 585 { 586 g_sequence_move (iter1, iter2); 587 588 if (!link2) 589 g_assert (g_sequence_iter_is_end (iter2)); 590 591 queue_insert_before (seq2, link2, link1->data); 592 593 g_queue_delete_link (seq1->queue, link1); 594 595 get_item (iter1)->seq = seq2; 596 597 seq1->n_items--; 598 seq2->n_items++; 599 } 600 601 check_integrity (seq); 602 603 iter1 = get_random_iter (seq, NULL); 604 605 /* Moving an iter to itself should have no effect */ 606 if (!g_sequence_iter_is_end (iter1)) 607 g_sequence_move (iter1, iter1); 608 } 609 break; 610 case SWAP: 611 { 612 GList *link1, *link2; 613 SequenceInfo *seq1 = RANDOM_SEQUENCE(); 614 SequenceInfo *seq2 = RANDOM_SEQUENCE(); 615 GSequenceIter *iter1 = get_random_iter (seq1, &link1); 616 GSequenceIter *iter2 = get_random_iter (seq2, &link2); 617 618 if (!g_sequence_iter_is_end (iter1) && 619 !g_sequence_iter_is_end (iter2)) 620 { 621 gpointer tmp; 622 623 g_sequence_swap (iter1, iter2); 624 625 get_item (iter1)->seq = seq2; 626 get_item (iter2)->seq = seq1; 627 628 tmp = link1->data; 629 link1->data = link2->data; 630 link2->data = tmp; 631 } 632 } 633 break; 634 case INSERT_SORTED: 635 { 636 int i; 637 dump_info (seq); 638 639 g_sequence_sort (seq->sequence, compare_items, NULL); 640 g_queue_sort (seq->queue, compare_iters, NULL); 641 642 check_sorted (seq); 643 644 for (i = 0; i < N_TIMES; ++i) 645 { 646 GSequenceIter *iter = 647 g_sequence_insert_sorted (seq->sequence, new_item(seq), compare_items, NULL); 648 649 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL); 650 } 651 652 check_sorted (seq); 653 654 dump_info (seq); 655 } 656 break; 657 case INSERT_SORTED_ITER: 658 { 659 int i; 660 dump_info (seq); 661 662 g_sequence_sort (seq->sequence, compare_items, NULL); 663 g_queue_sort (seq->queue, compare_iters, NULL); 664 665 check_sorted (seq); 666 667 for (i = 0; i < N_TIMES; ++i) 668 { 669 GSequenceIter *iter; 670 671 iter = g_sequence_insert_sorted_iter (seq->sequence, 672 new_item (seq), 673 (GSequenceIterCompareFunc)compare_iters, 674 seq->sequence); 675 676 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL); 677 } 678 679 check_sorted (seq); 680 681 dump_info (seq); 682 } 683 break; 684 case SORT_CHANGED: 685 { 686 int i; 687 688 g_sequence_sort (seq->sequence, compare_items, NULL); 689 g_queue_sort (seq->queue, compare_iters, NULL); 690 691 check_sorted (seq); 692 693 for (i = 0; i < N_TIMES; ++i) 694 { 695 GList *link; 696 GSequenceIter *iter = get_random_iter (seq, &link); 697 698 if (!g_sequence_iter_is_end (iter)) 699 { 700 g_sequence_set (iter, new_item (seq)); 701 g_sequence_sort_changed (iter, compare_items, NULL); 702 703 g_queue_delete_link (seq->queue, link); 704 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL); 705 } 706 707 check_sorted (seq); 708 } 709 } 710 break; 711 case SORT_CHANGED_ITER: 712 { 713 int i; 714 715 g_sequence_sort (seq->sequence, compare_items, NULL); 716 g_queue_sort (seq->queue, compare_iters, NULL); 717 718 check_sorted (seq); 719 720 for (i = 0; i < N_TIMES; ++i) 721 { 722 GList *link; 723 GSequenceIter *iter = get_random_iter (seq, &link); 724 725 if (!g_sequence_iter_is_end (iter)) 726 { 727 g_sequence_set (iter, new_item (seq)); 728 g_sequence_sort_changed_iter (iter, 729 (GSequenceIterCompareFunc)compare_iters, seq->sequence); 730 731 g_queue_delete_link (seq->queue, link); 732 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL); 733 } 734 735 check_sorted (seq); 736 } 737 } 738 break; 739 case REMOVE: 740 { 741 int i; 742 743 for (i = 0; i < N_TIMES; ++i) 744 { 745 GList *link; 746 GSequenceIter *iter = get_random_iter (seq, &link); 747 748 if (!g_sequence_iter_is_end (iter)) 749 { 750 g_sequence_remove (iter); 751 g_queue_delete_link (seq->queue, link); 752 } 753 } 754 } 755 break; 756 case REMOVE_RANGE: 757 { 758 GSequenceIter *begin_iter, *end_iter; 759 GList *begin_link, *end_link; 760 GList *list; 761 762 get_random_range (seq, &begin_iter, &end_iter, &begin_link, &end_link); 763 764 g_sequence_remove_range (begin_iter, end_iter); 765 766 list = begin_link; 767 while (list != end_link) 768 { 769 GList *next = list->next; 770 771 g_queue_delete_link (seq->queue, list); 772 773 list = next; 774 } 775 } 776 break; 777 case MOVE_RANGE: 778 { 779 SequenceInfo *src = RANDOM_SEQUENCE(); 780 SequenceInfo *dst = RANDOM_SEQUENCE(); 781 782 GSequenceIter *begin_iter, *end_iter; 783 GList *begin_link, *end_link; 784 785 GSequenceIter *dst_iter; 786 GList *dst_link; 787 788 GList *list; 789 790 g_assert (src->queue); 791 g_assert (dst->queue); 792 793 get_random_range (src, &begin_iter, &end_iter, &begin_link, &end_link); 794 dst_iter = get_random_iter (dst, &dst_link); 795 796 g_sequence_move_range (dst_iter, begin_iter, end_iter); 797 798 if (dst_link == begin_link || (src == dst && dst_link == end_link)) 799 { 800 check_integrity (src); 801 check_integrity (dst); 802 break; 803 } 804 805 if (queue_link_index (src, begin_link) >= 806 queue_link_index (src, end_link)) 807 { 808 break; 809 } 810 811 if (src == dst && 812 queue_link_index (src, dst_link) >= queue_link_index (src, begin_link) && 813 queue_link_index (src, dst_link) <= queue_link_index (src, end_link)) 814 { 815 break; 816 } 817 818 list = begin_link; 819 while (list != end_link) 820 { 821 GList *next = list->next; 822 Item *item = get_item (list->data); 823 824 g_assert (dst->queue); 825 queue_insert_before (dst, dst_link, list->data); 826 g_queue_delete_link (src->queue, list); 827 828 g_assert (item->seq == src); 829 830 src->n_items--; 831 dst->n_items++; 832 item->seq = dst; 833 834 list = next; 835 } 836 } 837 break; 838 case SEARCH: 839 { 840 Item *item; 841 GSequenceIter *search_iter; 842 GSequenceIter *insert_iter; 843 844 g_sequence_sort (seq->sequence, compare_items, NULL); 845 g_queue_sort (seq->queue, compare_iters, NULL); 846 847 check_sorted (seq); 848 849 item = new_item (seq); 850 search_iter = g_sequence_search (seq->sequence, item, compare_items, NULL); 851 852 insert_iter = g_sequence_insert_sorted (seq->sequence, item, compare_items, NULL); 853 854 g_assert (search_iter == g_sequence_iter_next (insert_iter)); 855 856 g_queue_insert_sorted (seq->queue, insert_iter, compare_iters, NULL); 857 } 858 break; 859 case SEARCH_ITER: 860 { 861 Item *item; 862 GSequenceIter *search_iter; 863 GSequenceIter *insert_iter; 864 865 g_sequence_sort (seq->sequence, compare_items, NULL); 866 g_queue_sort (seq->queue, compare_iters, NULL); 867 868 check_sorted (seq); 869 870 item = new_item (seq); 871 search_iter = g_sequence_search_iter (seq->sequence, 872 item, 873 (GSequenceIterCompareFunc)compare_iters, seq->sequence); 874 875 insert_iter = g_sequence_insert_sorted (seq->sequence, item, compare_items, NULL); 876 877 g_assert (search_iter == g_sequence_iter_next (insert_iter)); 878 879 g_queue_insert_sorted (seq->queue, insert_iter, compare_iters, NULL); 880 } 881 break; 882 883 /* dereferencing */ 884 case GET: 885 case SET: 886 { 887 GSequenceIter *iter; 888 GList *link; 889 890 iter = get_random_iter (seq, &link); 891 892 if (!g_sequence_iter_is_end (iter)) 893 { 894 Item *item; 895 int i; 896 897 check_integrity (seq); 898 899 /* Test basic functionality */ 900 item = new_item (seq); 901 g_sequence_set (iter, item); 902 g_assert (g_sequence_get (iter) == item); 903 904 /* Make sure that existing items are freed */ 905 for (i = 0; i < N_TIMES; ++i) 906 g_sequence_set (iter, new_item (seq)); 907 908 check_integrity (seq); 909 910 g_sequence_set (iter, new_item (seq)); 911 } 912 } 913 break; 914 915 /* operations on GSequenceIter * */ 916 case ITER_IS_BEGIN: 917 { 918 GSequenceIter *iter; 919 920 iter = g_sequence_get_iter_at_pos (seq->sequence, 0); 921 922 g_assert (g_sequence_iter_is_begin (iter)); 923 924 check_integrity (seq); 925 926 if (g_sequence_get_length (seq->sequence) > 0) 927 { 928 g_assert (!g_sequence_iter_is_begin (g_sequence_get_end_iter (seq->sequence))); 929 } 930 else 931 { 932 g_assert (g_sequence_iter_is_begin (g_sequence_get_end_iter (seq->sequence))); 933 } 934 935 g_assert (g_sequence_iter_is_begin (g_sequence_get_begin_iter (seq->sequence))); 936 } 937 break; 938 case ITER_IS_END: 939 { 940 GSequenceIter *iter; 941 int len = g_sequence_get_length (seq->sequence); 942 943 iter = g_sequence_get_iter_at_pos (seq->sequence, len); 944 945 g_assert (g_sequence_iter_is_end (iter)); 946 947 if (len > 0) 948 { 949 g_assert (!g_sequence_iter_is_end (g_sequence_get_begin_iter (seq->sequence))); 950 } 951 else 952 { 953 g_assert (g_sequence_iter_is_end (g_sequence_get_begin_iter (seq->sequence))); 954 } 955 956 g_assert (g_sequence_iter_is_end (g_sequence_get_end_iter (seq->sequence))); 957 } 958 break; 959 case ITER_NEXT: 960 { 961 GSequenceIter *iter1, *iter2, *iter3, *end; 962 963 iter1 = g_sequence_append (seq->sequence, new_item (seq)); 964 iter2 = g_sequence_append (seq->sequence, new_item (seq)); 965 iter3 = g_sequence_append (seq->sequence, new_item (seq)); 966 967 end = g_sequence_get_end_iter (seq->sequence); 968 969 g_assert (g_sequence_iter_next (iter1) == iter2); 970 g_assert (g_sequence_iter_next (iter2) == iter3); 971 g_assert (g_sequence_iter_next (iter3) == end); 972 g_assert (g_sequence_iter_next (end) == end); 973 974 g_queue_push_tail (seq->queue, iter1); 975 g_queue_push_tail (seq->queue, iter2); 976 g_queue_push_tail (seq->queue, iter3); 977 } 978 break; 979 case ITER_PREV: 980 { 981 GSequenceIter *iter1, *iter2, *iter3, *begin; 982 983 iter1 = g_sequence_prepend (seq->sequence, new_item (seq)); 984 iter2 = g_sequence_prepend (seq->sequence, new_item (seq)); 985 iter3 = g_sequence_prepend (seq->sequence, new_item (seq)); 986 987 begin = g_sequence_get_begin_iter (seq->sequence); 988 989 g_assert (g_sequence_iter_prev (iter1) == iter2); 990 g_assert (g_sequence_iter_prev (iter2) == iter3); 991 g_assert (iter3 == begin); 992 g_assert (g_sequence_iter_prev (iter3) == begin); 993 g_assert (g_sequence_iter_prev (begin) == begin); 994 995 g_queue_push_head (seq->queue, iter1); 996 g_queue_push_head (seq->queue, iter2); 997 g_queue_push_head (seq->queue, iter3); 998 } 999 break; 1000 case ITER_GET_POSITION: 1001 { 1002 GList *link; 1003 GSequenceIter *iter = get_random_iter (seq, &link); 1004 1005 g_assert (g_sequence_iter_get_position (iter) == 1006 queue_link_index (seq, link)); 1007 } 1008 break; 1009 case ITER_MOVE: 1010 { 1011 int len = g_sequence_get_length (seq->sequence); 1012 GSequenceIter *iter; 1013 int pos; 1014 1015 iter = get_random_iter (seq, NULL); 1016 pos = g_sequence_iter_get_position (iter); 1017 iter = g_sequence_iter_move (iter, len - pos); 1018 g_assert (g_sequence_iter_is_end (iter)); 1019 1020 1021 iter = get_random_iter (seq, NULL); 1022 pos = g_sequence_iter_get_position (iter); 1023 while (pos < len) 1024 { 1025 g_assert (!g_sequence_iter_is_end (iter)); 1026 pos++; 1027 iter = g_sequence_iter_move (iter, 1); 1028 } 1029 g_assert (g_sequence_iter_is_end (iter)); 1030 } 1031 break; 1032 case ITER_GET_SEQUENCE: 1033 { 1034 GSequenceIter *iter = get_random_iter (seq, NULL); 1035 1036 g_assert (g_sequence_iter_get_sequence (iter) == seq->sequence); 1037 } 1038 break; 1039 1040 /* search */ 1041 case ITER_COMPARE: 1042 { 1043 GList *link1, *link2; 1044 GSequenceIter *iter1 = get_random_iter (seq, &link1); 1045 GSequenceIter *iter2 = get_random_iter (seq, &link2); 1046 1047 int cmp = g_sequence_iter_compare (iter1, iter2); 1048 int pos1 = queue_link_index (seq, link1); 1049 int pos2 = queue_link_index (seq, link2); 1050 1051 if (cmp == 0) 1052 { 1053 g_assert (pos1 == pos2); 1054 } 1055 else if (cmp < 0) 1056 { 1057 g_assert (pos1 < pos2); 1058 } 1059 else 1060 { 1061 g_assert (pos1 > pos2); 1062 } 1063 } 1064 break; 1065 case RANGE_GET_MIDPOINT: 1066 { 1067 GSequenceIter *iter1 = get_random_iter (seq, NULL); 1068 GSequenceIter *iter2 = get_random_iter (seq, NULL); 1069 GSequenceIter *iter3; 1070 int cmp; 1071 1072 cmp = g_sequence_iter_compare (iter1, iter2); 1073 1074 if (cmp > 0) 1075 { 1076 GSequenceIter *tmp; 1077 1078 tmp = iter1; 1079 iter1 = iter2; 1080 iter2 = tmp; 1081 } 1082 1083 iter3 = g_sequence_range_get_midpoint (iter1, iter2); 1084 1085 if (cmp == 0) 1086 { 1087 g_assert (iter3 == iter1); 1088 g_assert (iter3 == iter2); 1089 } 1090 1091 g_assert (g_sequence_iter_get_position (iter3) >= 1092 g_sequence_iter_get_position (iter1)); 1093 g_assert (g_sequence_iter_get_position (iter2) >= 1094 g_sequence_iter_get_position (iter3)); 1095 } 1096 break; 1097 1098 } 1099 1100 check_integrity (seq); 1101 } 1102 } 1103 1104 /* Random seeds known to have failed at one point 1105 */ 1106 static gulong seeds[] = 1107 { 1108 825541564u, 1109 801678400u, 1110 1477639090u, 1111 3369132895u, 1112 1192944867u, 1113 770458294u, 1114 1099575817u, 1115 590523467u, 1116 3583571454u, 1117 579241222u 1118 }; 1119 1120 static void standalone_tests (void); 1121 1122 static guint32 1123 get_seed (int argc, char **argv) 1124 { 1125 if (argc > 1) 1126 { 1127 char *endptr; 1128 1129 return strtol (argv[1], &endptr, 0); 1130 } 1131 else 1132 { 1133 return g_random_int(); 1134 } 1135 } 1136 1137 int 1138 main (int argc, 1139 char **argv) 1140 { 1141 guint32 seed = get_seed (argc, argv); 1142 int i; 1143 1144 /* Run stand alone tests */ 1145 g_print ("running standalone tests\n"); 1146 standalone_tests(); 1147 1148 g_print ("running regression tests:\n"); 1149 /* Run regression tests */ 1150 for (i = 0; i < G_N_ELEMENTS (seeds); ++i) 1151 { 1152 run_random_tests (seeds[i]); 1153 } 1154 1155 /* Run with a new random seed */ 1156 g_print ("random seed:\n"); 1157 run_random_tests (seed); 1158 1159 1160 return 0; 1161 } 1162 1163 1164 /* Single, stand-alone tests */ 1165 1166 static void 1167 test_out_of_range_jump (void) 1168 { 1169 GSequence *seq = g_sequence_new (NULL); 1170 GSequenceIter *iter = g_sequence_get_begin_iter (seq); 1171 1172 g_sequence_iter_move (iter, 5); 1173 1174 g_assert (g_sequence_iter_is_begin (iter)); 1175 g_assert (g_sequence_iter_is_end (iter)); 1176 } 1177 1178 static int 1179 compare (gconstpointer a, gconstpointer b, gpointer userdata) 1180 { 1181 int ai, bi; 1182 1183 ai = GPOINTER_TO_INT (a); 1184 bi = GPOINTER_TO_INT (b); 1185 1186 if (ai < bi) 1187 return -1; 1188 else if (ai > bi) 1189 return 1; 1190 else 1191 return 0; 1192 } 1193 1194 static int 1195 compare_iter (GSequenceIter *a, 1196 GSequenceIter *b, 1197 gpointer data) 1198 { 1199 return compare (g_sequence_get (a), 1200 g_sequence_get (b), 1201 data); 1202 } 1203 1204 static void 1205 test_insert_sorted_non_pointer (void) 1206 { 1207 int i; 1208 1209 for (i = 0; i < 10; i++) 1210 { 1211 GSequence *seq = g_sequence_new (NULL); 1212 int j; 1213 1214 for (j = 0; j < 10000; j++) 1215 { 1216 g_sequence_insert_sorted (seq, GINT_TO_POINTER (g_random_int()), 1217 compare, NULL); 1218 1219 g_sequence_insert_sorted_iter (seq, GINT_TO_POINTER (g_random_int()), 1220 compare_iter, NULL); 1221 } 1222 1223 g_sequence_check (seq); 1224 1225 g_sequence_free (seq); 1226 } 1227 } 1228 1229 static void 1230 test_stable_sort (void) 1231 { 1232 int i; 1233 GSequence *seq = g_sequence_new (NULL); 1234 1235 #define N_ITEMS 1000 1236 1237 GSequenceIter *iters[N_ITEMS]; 1238 GSequenceIter *iter; 1239 1240 for (i = 0; i < N_ITEMS; ++i) 1241 { 1242 iters[i] = g_sequence_append (seq, GINT_TO_POINTER (3000)); 1243 g_sequence_check (seq); 1244 g_assert (g_sequence_iter_get_sequence (iters[i]) == seq); 1245 } 1246 1247 i = 0; 1248 iter = g_sequence_get_begin_iter (seq); 1249 g_assert (g_sequence_iter_get_sequence (iter) == seq); 1250 g_sequence_check (seq); 1251 while (!g_sequence_iter_is_end (iter)) 1252 { 1253 g_assert (g_sequence_iter_get_sequence (iters[i]) == seq); 1254 g_assert (iters[i++] == iter); 1255 1256 iter = g_sequence_iter_next (iter); 1257 g_sequence_check (seq); 1258 } 1259 1260 g_sequence_sort (seq, compare, NULL); 1261 1262 i = 0; 1263 iter = g_sequence_get_begin_iter (seq); 1264 while (!g_sequence_iter_is_end (iter)) 1265 { 1266 g_assert (g_sequence_iter_get_sequence (iters[i]) == seq); 1267 g_assert (iters[i] == iter); 1268 1269 iter = g_sequence_iter_next (iter); 1270 g_sequence_check (seq); 1271 1272 i++; 1273 } 1274 1275 for (i = N_ITEMS - 1; i >= 0; --i) 1276 { 1277 g_sequence_check (seq); 1278 g_assert (g_sequence_iter_get_sequence (iters[i]) == seq); 1279 g_assert (g_sequence_get_end_iter (seq) != iters[i]); 1280 g_sequence_sort_changed (iters[i], compare, NULL); 1281 } 1282 1283 i = 0; 1284 iter = g_sequence_get_begin_iter (seq); 1285 while (!g_sequence_iter_is_end (iter)) 1286 { 1287 g_assert (iters[i++] == iter); 1288 1289 iter = g_sequence_iter_next (iter); 1290 g_sequence_check (seq); 1291 } 1292 } 1293 1294 static void 1295 standalone_tests (void) 1296 { 1297 test_out_of_range_jump (); 1298 test_insert_sorted_non_pointer (); 1299 test_stable_sort (); 1300 } 1301 1302