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