Tizen 2.1 base
[platform/upstream/glib2.0.git] / tests / sequence-test.c
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