(root)/
m4-1.4.19/
tests/
test-array_oset.c
       1  /* Test of ordered set data type implementation.
       2     Copyright (C) 2006-2021 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2007.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <config.h>
      19  
      20  #include "gl_array_oset.h"
      21  
      22  #include <stdlib.h>
      23  #include <string.h>
      24  
      25  #include "gl_xlist.h"
      26  #include "gl_array_list.h"
      27  #include "macros.h"
      28  
      29  #include "test-oset-update.h"
      30  
      31  static const char *objects[30] =
      32    {
      33      "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
      34      "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "<", ">", "[", "]"
      35    };
      36  
      37  #define RANDOM(n) (rand () % (n))
      38  #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
      39  
      40  static void
      41  check_equals (gl_oset_t set1, gl_list_t set2)
      42  {
      43    size_t n = gl_oset_size (set1);
      44    gl_oset_iterator_t iter1;
      45    gl_list_iterator_t iter2;
      46    const void *elt1;
      47    const void *elt2;
      48    gl_list_node_t node2;
      49    size_t i;
      50  
      51    iter1 = gl_oset_iterator (set1);
      52    iter2 = gl_list_iterator (set2);
      53    for (i = 0; i < n; i++)
      54      {
      55        ASSERT (gl_oset_iterator_next (&iter1, &elt1));
      56        ASSERT (gl_list_iterator_next (&iter2, &elt2, &node2));
      57        ASSERT (elt1 == elt2);
      58      }
      59    ASSERT (!gl_oset_iterator_next (&iter1, &elt1));
      60    ASSERT (!gl_list_iterator_next (&iter2, &elt2, &node2));
      61    gl_oset_iterator_free (&iter1);
      62    gl_list_iterator_free (&iter2);
      63  }
      64  
      65  static void
      66  check_all (gl_oset_t set1, gl_list_t set2)
      67  {
      68    check_equals (set1, set2);
      69  }
      70  
      71  static bool
      72  is_at_least (const void *elt, const void *threshold)
      73  {
      74    return strcmp ((const char *) elt, (const char *) threshold) >= 0;
      75  }
      76  
      77  static size_t
      78  gl_sortedlist_indexof_atleast (gl_list_t set,
      79                                 gl_setelement_threshold_fn threshold_fn,
      80                                 const void *threshold)
      81  {
      82    /* This implementation is slow, but easy to verify.  */
      83    size_t count = gl_list_size (set);
      84    size_t index;
      85  
      86    for (index = 0; index < count; index++)
      87      if (threshold_fn (gl_list_get_at (set, index), threshold))
      88        return index;
      89    return (size_t)(-1);
      90  }
      91  
      92  int
      93  main (int argc, char *argv[])
      94  {
      95    gl_oset_t set1;
      96    gl_list_t set2;
      97  
      98    /* Allow the user to provide a non-default random seed on the command line.  */
      99    if (argc > 1)
     100      srand (atoi (argv[1]));
     101  
     102    {
     103      size_t initial_size = RANDOM (20);
     104      size_t i;
     105      unsigned int repeat;
     106  
     107      /* Create set1.  */
     108      set1 = gl_oset_nx_create_empty (GL_ARRAY_OSET, (gl_setelement_compar_fn) strcmp, NULL);
     109      ASSERT (set1 != NULL);
     110  
     111      /* Create set2.  */
     112      set2 = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, false);
     113  
     114      check_all (set1, set2);
     115  
     116      /* Initialize them.  */
     117      for (i = 0; i < initial_size; i++)
     118        {
     119          const char *obj = RANDOM_OBJECT ();
     120          ASSERT (gl_oset_nx_add (set1, obj)
     121                  == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL
     122                      ? false
     123                      : (gl_sortedlist_add (set2, (gl_listelement_compar_fn)strcmp, obj), true)));
     124          check_all (set1, set2);
     125        }
     126  
     127      for (repeat = 0; repeat < 100000; repeat++)
     128        {
     129          unsigned int operation = RANDOM (4);
     130          switch (operation)
     131            {
     132            case 0:
     133              {
     134                const char *obj = RANDOM_OBJECT ();
     135                ASSERT (gl_oset_search (set1, obj)
     136                        == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL));
     137              }
     138              break;
     139            case 1:
     140              {
     141                const char *obj = RANDOM_OBJECT ();
     142                ASSERT (gl_oset_nx_add (set1, obj)
     143                        == (gl_sortedlist_search (set2, (gl_listelement_compar_fn)strcmp, obj) != NULL
     144                            ? false
     145                            : (gl_sortedlist_add (set2, (gl_listelement_compar_fn)strcmp, obj), true)));
     146              }
     147              break;
     148            case 2:
     149              {
     150                const char *obj = RANDOM_OBJECT ();
     151                ASSERT (gl_oset_remove (set1, obj)
     152                        == gl_sortedlist_remove (set2, (gl_listelement_compar_fn)strcmp, obj));
     153              }
     154              break;
     155            case 3:
     156              {
     157                const char *obj = RANDOM_OBJECT ();
     158                gl_oset_iterator_t iter = gl_oset_iterator_atleast (set1, is_at_least, obj);
     159                size_t index = gl_sortedlist_indexof_atleast (set2, is_at_least, obj);
     160                const void *elt;
     161                /* Check the first two values that the iterator produces.
     162                   Checking them all would make this part of the test dominate the
     163                   run time of the test.  */
     164                if (index == (size_t)(-1))
     165                  ASSERT (!gl_oset_iterator_next (&iter, &elt));
     166                else
     167                  {
     168                    ASSERT (gl_oset_iterator_next (&iter, &elt));
     169                    ASSERT (elt == gl_list_get_at (set2, index));
     170                    if (index + 1 == gl_list_size (set2))
     171                      ASSERT (!gl_oset_iterator_next (&iter, &elt));
     172                    else
     173                      {
     174                        ASSERT (gl_oset_iterator_next (&iter, &elt));
     175                        ASSERT (elt == gl_list_get_at (set2, index + 1));
     176                      }
     177                  }
     178                gl_oset_iterator_free (&iter);
     179              }
     180              break;
     181            }
     182          check_all (set1, set2);
     183        }
     184  
     185      gl_oset_free (set1);
     186      gl_list_free (set2);
     187    }
     188  
     189    test_update (GL_ARRAY_OSET);
     190  
     191    return 0;
     192  }