root/maint/gnulib/tests/test-linkedhash_map.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. string_equals
  2. string_hash
  3. cmp_pairs_in_array
  4. check_equals
  5. check_all
  6. main

   1 /* Test of map data type implementation.
   2    Copyright (C) 2006-2021 Free Software Foundation, Inc.
   3    Written by Bruno Haible <bruno@clisp.org>, 2018.
   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_linkedhash_map.h"
  21 
  22 #include <limits.h>
  23 #include <stdlib.h>
  24 #include <string.h>
  25 
  26 #include "gl_array_map.h"
  27 #include "xalloc.h"
  28 #include "macros.h"
  29 
  30 static const char *objects[30] =
  31   {
  32     "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
  33     "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "<", ">", "[", "]"
  34   };
  35 
  36 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
  37 
  38 static bool
  39 string_equals (const void *x1, const void *x2)
     /* [previous][next][first][last][top][bottom][index][help] */
  40 {
  41   const char *s1 = x1;
  42   const char *s2 = x2;
  43   return strcmp (s1, s2) == 0;
  44 }
  45 
  46 /* A hash function for NUL-terminated char* strings using
  47    the method described by Bruno Haible.
  48    See https://www.haible.de/bruno/hashfunc.html.  */
  49 static size_t
  50 string_hash (const void *x)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52   const char *s = x;
  53   size_t h = 0;
  54 
  55   for (; *s; s++)
  56     h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
  57 
  58   return h;
  59 }
  60 
  61 #define RANDOM(n) (rand () % (n))
  62 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
  63 
  64 struct pair
  65 {
  66   const void *key;
  67   const void *value;
  68 };
  69 
  70 static int
  71 cmp_pairs_in_array (const void *pairptr1, const void *pairptr2)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73   const void *key1 = ((struct pair const *)pairptr1)->key;
  74   const void *key2 = ((struct pair const *)pairptr2)->key;
  75   return strcmp ((const char *) key1, (const char *) key2);
  76 }
  77 
  78 static void
  79 check_equals (gl_map_t map1, gl_map_t map2)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81   size_t n = gl_map_size (map1);
  82   struct pair *pairs_of_map1 = XNMALLOC (n, struct pair);
  83   struct pair *pairs_of_map2 = XNMALLOC (n, struct pair);
  84 
  85   gl_map_iterator_t iter1, iter2;
  86   const void *key1;
  87   const void *value1;
  88   const void *key2;
  89   const void *value2;
  90   size_t i;
  91 
  92   iter1 = gl_map_iterator (map1);
  93   iter2 = gl_map_iterator (map2);
  94   for (i = 0; i < n; i++)
  95     {
  96       ASSERT (gl_map_iterator_next (&iter1, &key1, &value1));
  97       ASSERT (gl_map_iterator_next (&iter2, &key2, &value2));
  98       pairs_of_map1[i].key = key1;
  99       pairs_of_map1[i].value = value1;
 100       pairs_of_map2[i].key = key2;
 101       pairs_of_map2[i].value = value2;
 102     }
 103   ASSERT (!gl_map_iterator_next (&iter1, &key1, &value1));
 104   ASSERT (!gl_map_iterator_next (&iter2, &key2, &value2));
 105   gl_map_iterator_free (&iter1);
 106   gl_map_iterator_free (&iter2);
 107 
 108   if (n > 0)
 109     {
 110       qsort (pairs_of_map1, n, sizeof (struct pair), cmp_pairs_in_array);
 111       qsort (pairs_of_map2, n, sizeof (struct pair), cmp_pairs_in_array);
 112     }
 113   for (i = 0; i < n; i++)
 114     {
 115       ASSERT (pairs_of_map1[i].key == pairs_of_map2[i].key);
 116       ASSERT (pairs_of_map1[i].value == pairs_of_map2[i].value);
 117     }
 118   free (pairs_of_map2);
 119   free (pairs_of_map1);
 120 }
 121 
 122 static void
 123 check_all (gl_map_t map1, gl_map_t map2)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125   check_equals (map1, map2);
 126 }
 127 
 128 int
 129 main (int argc, char *argv[])
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131   gl_map_t map1, map2;
 132 
 133   /* Allow the user to provide a non-default random seed on the command line.  */
 134   if (argc > 1)
 135     srand (atoi (argv[1]));
 136 
 137   {
 138     size_t initial_size = RANDOM (20);
 139     size_t i;
 140     unsigned int repeat;
 141 
 142     /* Create map1.  */
 143     map1 = gl_map_nx_create_empty (GL_ARRAY_MAP,
 144                                    string_equals, string_hash, NULL, NULL);
 145     ASSERT (map1 != NULL);
 146 
 147     /* Create map2.  */
 148     map2 = gl_map_nx_create_empty (GL_LINKEDHASH_MAP,
 149                                    string_equals, string_hash, NULL, NULL);
 150     ASSERT (map2 != NULL);
 151 
 152     check_all (map1, map2);
 153 
 154     /* Initialize them.  */
 155     for (i = 0; i < initial_size; i++)
 156       {
 157         const char *key = RANDOM_OBJECT ();
 158         const char *value = RANDOM_OBJECT ();
 159         ASSERT (gl_map_nx_put (map1, key, value) == gl_map_nx_put (map2, key, value));
 160         check_all (map1, map2);
 161       }
 162 
 163     for (repeat = 0; repeat < 100000; repeat++)
 164       {
 165         unsigned int operation = RANDOM (3);
 166         switch (operation)
 167           {
 168           case 0:
 169             {
 170               const char *key = RANDOM_OBJECT ();
 171               ASSERT (gl_map_get (map1, key) == gl_map_get (map2, key));
 172             }
 173             break;
 174           case 1:
 175             {
 176               const char *key = RANDOM_OBJECT ();
 177               const char *value = RANDOM_OBJECT ();
 178               ASSERT (gl_map_nx_put (map1, key, value) == gl_map_nx_put (map2, key, value));
 179             }
 180             break;
 181           case 2:
 182             {
 183               const char *key = RANDOM_OBJECT ();
 184               ASSERT (gl_map_remove (map1, key) == gl_map_remove (map2, key));
 185             }
 186             break;
 187           }
 188         check_all (map1, map2);
 189       }
 190 
 191     gl_map_free (map1);
 192     gl_map_free (map2);
 193   }
 194 
 195   return 0;
 196 }

/* [previous][next][first][last][top][bottom][index][help] */