2.25.2
[glib.git] / tests / sequence-test.c
blob2a88c7df472df0f46117127f619ee08a852fcf94
1 #include <stdio.h>
2 #include <glib.h>
3 #include <stdlib.h>
5 /* Keep this in sync with gsequence.c !!! */
6 typedef struct _GSequenceNode GSequenceNode;
8 struct _GSequence
10 GSequenceNode * end_node;
11 GDestroyNotify data_destroy_notify;
12 gboolean access_prohibited;
13 GSequence * real_sequence;
16 struct _GSequenceNode
18 gint n_nodes;
19 GSequenceNode * parent;
20 GSequenceNode * left;
21 GSequenceNode * right;
22 gpointer data;
25 static guint
26 get_priority (GSequenceNode *node)
28 guint key = GPOINTER_TO_UINT (node);
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);
37 return key? key : 1;
40 static void
41 check_node (GSequenceNode *node)
43 if (node)
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);
58 void
59 g_sequence_check (GSequence *seq)
61 GSequenceNode *node = seq->end_node;
63 while (node->parent)
64 node = node->parent;
66 check_node (node);
68 while (node->right)
69 node = node->right;
71 g_assert (seq->end_node == node);
72 g_assert (node->data == seq);
77 enum {
78 NEW, FREE, GET_LENGTH, FOREACH, FOREACH_RANGE, SORT, SORT_ITER,
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,
85 /* dereferencing */
86 GET, SET,
88 /* operations on GSequenceIter * */
89 ITER_IS_BEGIN, ITER_IS_END, ITER_NEXT, ITER_PREV, ITER_GET_POSITION,
90 ITER_MOVE, ITER_GET_SEQUENCE,
92 /* search */
93 ITER_COMPARE, RANGE_GET_MIDPOINT,
94 N_OPS
97 typedef struct SequenceInfo
99 GQueue * queue;
100 GSequence * sequence;
101 int n_items;
102 } SequenceInfo;
104 typedef struct
106 SequenceInfo *seq;
107 int number;
108 } Item;
110 void g_sequence_check (GSequence *sequence);
112 static Item *
113 fix_pointer (gconstpointer data)
115 return (Item *)((char *)data - 1);
118 static Item *
119 get_item (GSequenceIter *iter)
121 return fix_pointer (g_sequence_get (iter));
124 static void
125 check_integrity (SequenceInfo *info)
127 GList *list;
128 GSequenceIter *iter;
129 int i;
131 g_sequence_check (info->sequence);
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);
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))
144 Item *item;
145 g_assert (list->data == iter);
146 item = get_item (list->data);
147 g_assert (item->seq == info);
149 iter = g_sequence_iter_next (iter);
150 list = list->next;
151 i++;
154 g_assert (info->n_items == g_queue_get_length (info->queue));
155 g_assert (g_sequence_get_length (info->sequence) == info->n_items);
158 static gpointer
159 new_item (SequenceInfo *seq)
161 Item *item = g_new (Item, 1);
162 seq->n_items++;
163 item->seq = seq;
164 item->number = g_random_int ();
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
170 return ((char *)item + 1);
173 static void
174 free_item (gpointer data)
176 Item *item = fix_pointer (data);
177 item->seq->n_items--;
178 g_free (item);
181 static void
182 seq_foreach (gpointer data,
183 gpointer user_data)
185 Item *item = fix_pointer (data);
186 GList **link = user_data;
187 GSequenceIter *iter;
189 g_assert (*link != NULL);
191 iter = (*link)->data;
193 g_assert (get_item (iter) == item);
195 item->number = g_random_int();
197 *link = (*link)->next;
200 static gint
201 compare_items (gconstpointer a,
202 gconstpointer b,
203 gpointer data)
205 const Item *item_a = fix_pointer (a);
206 const Item *item_b = fix_pointer (b);
208 if (item_a->number < item_b->number)
210 return -1;
212 else if (item_a->number == item_b->number)
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.
220 if (item_a < item_b)
221 return -1;
222 else if (item_a == item_b)
223 return 0;
224 else
225 return 1;
227 else
229 return 1;
233 static void
234 check_sorted (SequenceInfo *info)
236 GList *list;
237 int last;
238 GSequenceIter *last_iter;
240 check_integrity (info);
242 last = G_MININT;
243 last_iter = NULL;
244 for (list = info->queue->head; list != NULL; list = list->next)
246 GSequenceIter *iter = list->data;
247 Item *item = get_item (iter);
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
253 if (last_iter)
254 g_assert (iter == g_sequence_iter_next (last_iter));
256 last = item->number;
257 last_iter = iter;
261 static gint
262 compare_iters (gconstpointer a,
263 gconstpointer b,
264 gpointer data)
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);
273 if (seq)
275 g_assert (g_sequence_iter_get_sequence (iter_a) == seq);
276 g_assert (g_sequence_iter_get_sequence (iter_b) == seq);
279 return compare_items (item_a, item_b, data);
282 /* A version of g_queue_link_index() that treats NULL as just
283 * beyond the queue
285 static int
286 queue_link_index (SequenceInfo *seq, GList *link)
288 if (link)
289 return g_queue_link_index (seq->queue, link);
290 else
291 return g_queue_get_length (seq->queue);
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)
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);
305 g_assert (length == g_sequence_get_length (seq->sequence));
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)
317 g_assert (
318 queue_link_index (seq, *begin_link) ==
319 g_sequence_iter_get_position (*begin_iter));
321 if (end_iter && end_link)
323 g_assert (
324 queue_link_index (seq, *end_link) ==
325 g_sequence_iter_get_position (*end_iter));
329 static gint
330 get_random_position (SequenceInfo *seq)
332 int length = g_queue_get_length (seq->queue);
334 g_assert (length == g_sequence_get_length (seq->sequence));
336 return g_random_int_range (-2, length + 5);
339 static GSequenceIter *
340 get_random_iter (SequenceInfo *seq,
341 GList **link)
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;
353 static void
354 dump_info (SequenceInfo *seq)
356 #if 0
357 GSequenceIter *iter;
358 GList *list;
360 iter = g_sequence_get_begin_iter (seq->sequence);
361 list = seq->queue->head;
363 while (iter != g_sequence_get_end_iter (seq->sequence))
365 Item *item = get_item (iter);
366 g_print ("%p %p %d\n", list->data, iter, item->number);
368 iter = g_sequence_iter_next (iter);
369 list = list->next;
371 #endif
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)
378 if (link)
379 g_queue_insert_before (seq->queue, link, data);
380 else
381 g_queue_push_tail (seq->queue, data);
384 static void
385 run_random_tests (guint32 seed)
387 #define N_ITERATIONS 60000
388 #define N_SEQUENCES 8
389 #define N_TIMES 24
391 SequenceInfo sequences[N_SEQUENCES];
392 int k;
394 g_print (" seed: %u\n", seed);
396 g_random_set_seed (seed);
398 for (k = 0; k < N_SEQUENCES; ++k)
400 sequences[k].queue = g_queue_new ();
401 sequences[k].sequence = g_sequence_new (free_item);
402 sequences[k].n_items = 0;
405 #define RANDOM_SEQUENCE() &(sequences[g_random_int_range (0, N_SEQUENCES)])
407 for (k = 0; k < N_ITERATIONS; ++k)
409 int i;
410 SequenceInfo *seq = RANDOM_SEQUENCE();
411 int op = g_random_int_range (0, N_OPS);
413 #if 0
414 g_print ("%d on %p\n", op, seq);
415 #endif
417 switch (op)
419 case NEW:
420 case FREE:
422 g_queue_free (seq->queue);
423 g_sequence_free (seq->sequence);
425 g_assert (seq->n_items == 0);
427 seq->queue = g_queue_new ();
428 seq->sequence = g_sequence_new (free_item);
430 check_integrity (seq);
432 break;
433 case GET_LENGTH:
435 int slen = g_sequence_get_length (seq->sequence);
436 int qlen = g_queue_get_length (seq->queue);
438 g_assert (slen == qlen);
440 break;
441 case FOREACH:
443 GList *link = seq->queue->head;
444 g_sequence_foreach (seq->sequence, seq_foreach, &link);
445 g_assert (link == NULL);
447 break;
448 case FOREACH_RANGE:
450 GSequenceIter *begin_iter, *end_iter;
451 GList *begin_link, *end_link;
453 get_random_range (seq, &begin_iter, &end_iter, &begin_link, &end_link);
455 check_integrity (seq);
457 g_sequence_foreach_range (begin_iter, end_iter, seq_foreach, &begin_link);
459 g_assert (begin_link == end_link);
461 break;
462 case SORT:
464 dump_info (seq);
466 g_sequence_sort (seq->sequence, compare_items, NULL);
467 g_queue_sort (seq->queue, compare_iters, NULL);
469 check_sorted (seq);
471 dump_info (seq);
473 break;
474 case SORT_ITER:
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);
482 break;
484 /* Getting iters */
485 case GET_END_ITER:
486 case GET_BEGIN_ITER:
488 GSequenceIter *begin_iter;
489 GSequenceIter *end_iter;
490 GSequenceIter *penultimate_iter;
492 begin_iter = g_sequence_get_begin_iter (seq->sequence);
493 check_integrity (seq);
495 end_iter = g_sequence_get_end_iter (seq->sequence);
496 check_integrity (seq);
498 penultimate_iter = g_sequence_iter_prev (end_iter);
499 check_integrity (seq);
501 if (g_sequence_get_length (seq->sequence) > 0)
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);
508 else
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);
517 break;
518 case GET_ITER_AT_POS:
520 int i;
522 g_assert (g_queue_get_length (seq->queue) == g_sequence_get_length (seq->sequence));
524 for (i = 0; i < 10; ++i)
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)
532 g_assert (iter == g_sequence_get_end_iter (seq->sequence));
533 g_assert (link == NULL);
535 else
537 g_assert (link);
538 g_assert (link->data == iter);
542 break;
543 case APPEND:
545 for (i = 0; i < 10; ++i)
547 GSequenceIter *iter = g_sequence_append (seq->sequence, new_item (seq));
548 g_queue_push_tail (seq->queue, iter);
551 break;
552 case PREPEND:
554 for (i = 0; i < 10; ++i)
556 GSequenceIter *iter = g_sequence_prepend (seq->sequence, new_item (seq));
557 g_queue_push_head (seq->queue, iter);
560 break;
561 case INSERT_BEFORE:
563 for (i = 0; i < 10; ++i)
565 GList *link;
566 GSequenceIter *iter = get_random_iter (seq, &link);
567 GSequenceIter *new_iter;
568 check_integrity (seq);
570 new_iter = g_sequence_insert_before (iter, new_item (seq));
572 queue_insert_before (seq, link, new_iter);
575 break;
576 case MOVE:
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);
584 if (!g_sequence_iter_is_end (iter1))
586 g_sequence_move (iter1, iter2);
588 if (!link2)
589 g_assert (g_sequence_iter_is_end (iter2));
591 queue_insert_before (seq2, link2, link1->data);
593 g_queue_delete_link (seq1->queue, link1);
595 get_item (iter1)->seq = seq2;
597 seq1->n_items--;
598 seq2->n_items++;
601 check_integrity (seq);
603 iter1 = get_random_iter (seq, NULL);
605 /* Moving an iter to itself should have no effect */
606 if (!g_sequence_iter_is_end (iter1))
607 g_sequence_move (iter1, iter1);
609 break;
610 case SWAP:
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);
618 if (!g_sequence_iter_is_end (iter1) &&
619 !g_sequence_iter_is_end (iter2))
621 gpointer tmp;
623 g_sequence_swap (iter1, iter2);
625 get_item (iter1)->seq = seq2;
626 get_item (iter2)->seq = seq1;
628 tmp = link1->data;
629 link1->data = link2->data;
630 link2->data = tmp;
633 break;
634 case INSERT_SORTED:
636 int i;
637 dump_info (seq);
639 g_sequence_sort (seq->sequence, compare_items, NULL);
640 g_queue_sort (seq->queue, compare_iters, NULL);
642 check_sorted (seq);
644 for (i = 0; i < N_TIMES; ++i)
646 GSequenceIter *iter =
647 g_sequence_insert_sorted (seq->sequence, new_item(seq), compare_items, NULL);
649 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL);
652 check_sorted (seq);
654 dump_info (seq);
656 break;
657 case INSERT_SORTED_ITER:
659 int i;
660 dump_info (seq);
662 g_sequence_sort (seq->sequence, compare_items, NULL);
663 g_queue_sort (seq->queue, compare_iters, NULL);
665 check_sorted (seq);
667 for (i = 0; i < N_TIMES; ++i)
669 GSequenceIter *iter;
671 iter = g_sequence_insert_sorted_iter (seq->sequence,
672 new_item (seq),
673 (GSequenceIterCompareFunc)compare_iters,
674 seq->sequence);
676 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL);
679 check_sorted (seq);
681 dump_info (seq);
683 break;
684 case SORT_CHANGED:
686 int i;
688 g_sequence_sort (seq->sequence, compare_items, NULL);
689 g_queue_sort (seq->queue, compare_iters, NULL);
691 check_sorted (seq);
693 for (i = 0; i < N_TIMES; ++i)
695 GList *link;
696 GSequenceIter *iter = get_random_iter (seq, &link);
698 if (!g_sequence_iter_is_end (iter))
700 g_sequence_set (iter, new_item (seq));
701 g_sequence_sort_changed (iter, compare_items, NULL);
703 g_queue_delete_link (seq->queue, link);
704 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL);
707 check_sorted (seq);
710 break;
711 case SORT_CHANGED_ITER:
713 int i;
715 g_sequence_sort (seq->sequence, compare_items, NULL);
716 g_queue_sort (seq->queue, compare_iters, NULL);
718 check_sorted (seq);
720 for (i = 0; i < N_TIMES; ++i)
722 GList *link;
723 GSequenceIter *iter = get_random_iter (seq, &link);
725 if (!g_sequence_iter_is_end (iter))
727 g_sequence_set (iter, new_item (seq));
728 g_sequence_sort_changed_iter (iter,
729 (GSequenceIterCompareFunc)compare_iters, seq->sequence);
731 g_queue_delete_link (seq->queue, link);
732 g_queue_insert_sorted (seq->queue, iter, compare_iters, NULL);
735 check_sorted (seq);
738 break;
739 case REMOVE:
741 int i;
743 for (i = 0; i < N_TIMES; ++i)
745 GList *link;
746 GSequenceIter *iter = get_random_iter (seq, &link);
748 if (!g_sequence_iter_is_end (iter))
750 g_sequence_remove (iter);
751 g_queue_delete_link (seq->queue, link);
755 break;
756 case REMOVE_RANGE:
758 GSequenceIter *begin_iter, *end_iter;
759 GList *begin_link, *end_link;
760 GList *list;
762 get_random_range (seq, &begin_iter, &end_iter, &begin_link, &end_link);
764 g_sequence_remove_range (begin_iter, end_iter);
766 list = begin_link;
767 while (list != end_link)
769 GList *next = list->next;
771 g_queue_delete_link (seq->queue, list);
773 list = next;
776 break;
777 case MOVE_RANGE:
779 SequenceInfo *src = RANDOM_SEQUENCE();
780 SequenceInfo *dst = RANDOM_SEQUENCE();
782 GSequenceIter *begin_iter, *end_iter;
783 GList *begin_link, *end_link;
785 GSequenceIter *dst_iter;
786 GList *dst_link;
788 GList *list;
790 g_assert (src->queue);
791 g_assert (dst->queue);
793 get_random_range (src, &begin_iter, &end_iter, &begin_link, &end_link);
794 dst_iter = get_random_iter (dst, &dst_link);
796 g_sequence_move_range (dst_iter, begin_iter, end_iter);
798 if (dst_link == begin_link || (src == dst && dst_link == end_link))
800 check_integrity (src);
801 check_integrity (dst);
802 break;
805 if (queue_link_index (src, begin_link) >=
806 queue_link_index (src, end_link))
808 break;
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))
815 break;
818 list = begin_link;
819 while (list != end_link)
821 GList *next = list->next;
822 Item *item = get_item (list->data);
824 g_assert (dst->queue);
825 queue_insert_before (dst, dst_link, list->data);
826 g_queue_delete_link (src->queue, list);
828 g_assert (item->seq == src);
830 src->n_items--;
831 dst->n_items++;
832 item->seq = dst;
834 list = next;
837 break;
838 case SEARCH:
840 Item *item;
841 GSequenceIter *search_iter;
842 GSequenceIter *insert_iter;
844 g_sequence_sort (seq->sequence, compare_items, NULL);
845 g_queue_sort (seq->queue, compare_iters, NULL);
847 check_sorted (seq);
849 item = new_item (seq);
850 search_iter = g_sequence_search (seq->sequence, item, compare_items, NULL);
852 insert_iter = g_sequence_insert_sorted (seq->sequence, item, compare_items, NULL);
854 g_assert (search_iter == g_sequence_iter_next (insert_iter));
856 g_queue_insert_sorted (seq->queue, insert_iter, compare_iters, NULL);
858 break;
859 case SEARCH_ITER:
861 Item *item;
862 GSequenceIter *search_iter;
863 GSequenceIter *insert_iter;
865 g_sequence_sort (seq->sequence, compare_items, NULL);
866 g_queue_sort (seq->queue, compare_iters, NULL);
868 check_sorted (seq);
870 item = new_item (seq);
871 search_iter = g_sequence_search_iter (seq->sequence,
872 item,
873 (GSequenceIterCompareFunc)compare_iters, seq->sequence);
875 insert_iter = g_sequence_insert_sorted (seq->sequence, item, compare_items, NULL);
877 g_assert (search_iter == g_sequence_iter_next (insert_iter));
879 g_queue_insert_sorted (seq->queue, insert_iter, compare_iters, NULL);
881 break;
883 /* dereferencing */
884 case GET:
885 case SET:
887 GSequenceIter *iter;
888 GList *link;
890 iter = get_random_iter (seq, &link);
892 if (!g_sequence_iter_is_end (iter))
894 Item *item;
895 int i;
897 check_integrity (seq);
899 /* Test basic functionality */
900 item = new_item (seq);
901 g_sequence_set (iter, item);
902 g_assert (g_sequence_get (iter) == item);
904 /* Make sure that existing items are freed */
905 for (i = 0; i < N_TIMES; ++i)
906 g_sequence_set (iter, new_item (seq));
908 check_integrity (seq);
910 g_sequence_set (iter, new_item (seq));
913 break;
915 /* operations on GSequenceIter * */
916 case ITER_IS_BEGIN:
918 GSequenceIter *iter;
920 iter = g_sequence_get_iter_at_pos (seq->sequence, 0);
922 g_assert (g_sequence_iter_is_begin (iter));
924 check_integrity (seq);
926 if (g_sequence_get_length (seq->sequence) > 0)
928 g_assert (!g_sequence_iter_is_begin (g_sequence_get_end_iter (seq->sequence)));
930 else
932 g_assert (g_sequence_iter_is_begin (g_sequence_get_end_iter (seq->sequence)));
935 g_assert (g_sequence_iter_is_begin (g_sequence_get_begin_iter (seq->sequence)));
937 break;
938 case ITER_IS_END:
940 GSequenceIter *iter;
941 int len = g_sequence_get_length (seq->sequence);
943 iter = g_sequence_get_iter_at_pos (seq->sequence, len);
945 g_assert (g_sequence_iter_is_end (iter));
947 if (len > 0)
949 g_assert (!g_sequence_iter_is_end (g_sequence_get_begin_iter (seq->sequence)));
951 else
953 g_assert (g_sequence_iter_is_end (g_sequence_get_begin_iter (seq->sequence)));
956 g_assert (g_sequence_iter_is_end (g_sequence_get_end_iter (seq->sequence)));
958 break;
959 case ITER_NEXT:
961 GSequenceIter *iter1, *iter2, *iter3, *end;
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));
967 end = g_sequence_get_end_iter (seq->sequence);
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);
974 g_queue_push_tail (seq->queue, iter1);
975 g_queue_push_tail (seq->queue, iter2);
976 g_queue_push_tail (seq->queue, iter3);
978 break;
979 case ITER_PREV:
981 GSequenceIter *iter1, *iter2, *iter3, *begin;
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));
987 begin = g_sequence_get_begin_iter (seq->sequence);
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);
995 g_queue_push_head (seq->queue, iter1);
996 g_queue_push_head (seq->queue, iter2);
997 g_queue_push_head (seq->queue, iter3);
999 break;
1000 case ITER_GET_POSITION:
1002 GList *link;
1003 GSequenceIter *iter = get_random_iter (seq, &link);
1005 g_assert (g_sequence_iter_get_position (iter) ==
1006 queue_link_index (seq, link));
1008 break;
1009 case ITER_MOVE:
1011 int len = g_sequence_get_length (seq->sequence);
1012 GSequenceIter *iter;
1013 int pos;
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));
1021 iter = get_random_iter (seq, NULL);
1022 pos = g_sequence_iter_get_position (iter);
1023 while (pos < len)
1025 g_assert (!g_sequence_iter_is_end (iter));
1026 pos++;
1027 iter = g_sequence_iter_move (iter, 1);
1029 g_assert (g_sequence_iter_is_end (iter));
1031 break;
1032 case ITER_GET_SEQUENCE:
1034 GSequenceIter *iter = get_random_iter (seq, NULL);
1036 g_assert (g_sequence_iter_get_sequence (iter) == seq->sequence);
1038 break;
1040 /* search */
1041 case ITER_COMPARE:
1043 GList *link1, *link2;
1044 GSequenceIter *iter1 = get_random_iter (seq, &link1);
1045 GSequenceIter *iter2 = get_random_iter (seq, &link2);
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);
1051 if (cmp == 0)
1053 g_assert (pos1 == pos2);
1055 else if (cmp < 0)
1057 g_assert (pos1 < pos2);
1059 else
1061 g_assert (pos1 > pos2);
1064 break;
1065 case RANGE_GET_MIDPOINT:
1067 GSequenceIter *iter1 = get_random_iter (seq, NULL);
1068 GSequenceIter *iter2 = get_random_iter (seq, NULL);
1069 GSequenceIter *iter3;
1070 int cmp;
1072 cmp = g_sequence_iter_compare (iter1, iter2);
1074 if (cmp > 0)
1076 GSequenceIter *tmp;
1078 tmp = iter1;
1079 iter1 = iter2;
1080 iter2 = tmp;
1083 iter3 = g_sequence_range_get_midpoint (iter1, iter2);
1085 if (cmp == 0)
1087 g_assert (iter3 == iter1);
1088 g_assert (iter3 == iter2);
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));
1096 break;
1100 check_integrity (seq);
1104 /* Random seeds known to have failed at one point
1106 static gulong seeds[] =
1108 825541564u,
1109 801678400u,
1110 1477639090u,
1111 3369132895u,
1112 1192944867u,
1113 770458294u,
1114 1099575817u,
1115 590523467u,
1116 3583571454u,
1117 579241222u
1120 static void standalone_tests (void);
1122 static guint32
1123 get_seed (int argc, char **argv)
1125 if (argc > 1)
1127 char *endptr;
1129 return strtol (argv[1], &endptr, 0);
1131 else
1133 return g_random_int();
1138 main (int argc,
1139 char **argv)
1141 guint32 seed = get_seed (argc, argv);
1142 int i;
1144 /* Run stand alone tests */
1145 g_print ("running standalone tests\n");
1146 standalone_tests();
1148 g_print ("running regression tests:\n");
1149 /* Run regression tests */
1150 for (i = 0; i < G_N_ELEMENTS (seeds); ++i)
1152 run_random_tests (seeds[i]);
1155 /* Run with a new random seed */
1156 g_print ("random seed:\n");
1157 run_random_tests (seed);
1160 return 0;
1164 /* Single, stand-alone tests */
1166 static void
1167 test_out_of_range_jump (void)
1169 GSequence *seq = g_sequence_new (NULL);
1170 GSequenceIter *iter = g_sequence_get_begin_iter (seq);
1172 g_sequence_iter_move (iter, 5);
1174 g_assert (g_sequence_iter_is_begin (iter));
1175 g_assert (g_sequence_iter_is_end (iter));
1178 static int
1179 compare (gconstpointer a, gconstpointer b, gpointer userdata)
1181 int ai, bi;
1183 ai = GPOINTER_TO_INT (a);
1184 bi = GPOINTER_TO_INT (b);
1186 if (ai < bi)
1187 return -1;
1188 else if (ai > bi)
1189 return 1;
1190 else
1191 return 0;
1194 static int
1195 compare_iter (GSequenceIter *a,
1196 GSequenceIter *b,
1197 gpointer data)
1199 return compare (g_sequence_get (a),
1200 g_sequence_get (b),
1201 data);
1204 static void
1205 test_insert_sorted_non_pointer (void)
1207 int i;
1209 for (i = 0; i < 10; i++)
1211 GSequence *seq = g_sequence_new (NULL);
1212 int j;
1214 for (j = 0; j < 10000; j++)
1216 g_sequence_insert_sorted (seq, GINT_TO_POINTER (g_random_int()),
1217 compare, NULL);
1219 g_sequence_insert_sorted_iter (seq, GINT_TO_POINTER (g_random_int()),
1220 compare_iter, NULL);
1223 g_sequence_check (seq);
1225 g_sequence_free (seq);
1229 static void
1230 test_stable_sort (void)
1232 int i;
1233 GSequence *seq = g_sequence_new (NULL);
1235 #define N_ITEMS 1000
1237 GSequenceIter *iters[N_ITEMS];
1238 GSequenceIter *iter;
1240 for (i = 0; i < N_ITEMS; ++i)
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);
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))
1253 g_assert (g_sequence_iter_get_sequence (iters[i]) == seq);
1254 g_assert (iters[i++] == iter);
1256 iter = g_sequence_iter_next (iter);
1257 g_sequence_check (seq);
1260 g_sequence_sort (seq, compare, NULL);
1262 i = 0;
1263 iter = g_sequence_get_begin_iter (seq);
1264 while (!g_sequence_iter_is_end (iter))
1266 g_assert (g_sequence_iter_get_sequence (iters[i]) == seq);
1267 g_assert (iters[i] == iter);
1269 iter = g_sequence_iter_next (iter);
1270 g_sequence_check (seq);
1272 i++;
1275 for (i = N_ITEMS - 1; i >= 0; --i)
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);
1283 i = 0;
1284 iter = g_sequence_get_begin_iter (seq);
1285 while (!g_sequence_iter_is_end (iter))
1287 g_assert (iters[i++] == iter);
1289 iter = g_sequence_iter_next (iter);
1290 g_sequence_check (seq);
1294 static void
1295 standalone_tests (void)
1297 test_out_of_range_jump ();
1298 test_insert_sorted_non_pointer ();
1299 test_stable_sort ();