1 /* Test of map data type implementation.
2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2018.
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.
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.
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/>. */
20 #include "gl_hash_map.h"
26 #include "gl_array_map.h"
30 static const char *objects
[30] =
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", "<", ">", "[", "]"
36 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
39 string_equals (const void *x1
, const void *x2
)
43 return strcmp (s1
, s2
) == 0;
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. */
50 string_hash (const void *x
)
56 h
= *s
+ ((h
<< 9) | (h
>> (SIZE_BITS
- 9)));
61 #define RANDOM(n) (rand () % (n))
62 #define RANDOM_OBJECT() objects[RANDOM (SIZEOF (objects))]
71 cmp_pairs_in_array (const void *pairptr1
, const void *pairptr2
)
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
);
79 check_equals (gl_map_t map1
, gl_map_t map2
)
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
);
85 gl_map_iterator_t iter1
, iter2
;
92 iter1
= gl_map_iterator (map1
);
93 iter2
= gl_map_iterator (map2
);
94 for (i
= 0; i
< n
; i
++)
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
;
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
);
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
);
113 for (i
= 0; i
< n
; i
++)
115 ASSERT (pairs_of_map1
[i
].key
== pairs_of_map2
[i
].key
);
116 ASSERT (pairs_of_map1
[i
].value
== pairs_of_map2
[i
].value
);
118 free (pairs_of_map2
);
119 free (pairs_of_map1
);
123 check_all (gl_map_t map1
, gl_map_t map2
)
125 check_equals (map1
, map2
);
129 main (int argc
, char *argv
[])
133 /* Allow the user to provide a non-default random seed on the command line. */
135 srand (atoi (argv
[1]));
138 size_t initial_size
= RANDOM (20);
143 map1
= gl_map_nx_create_empty (GL_ARRAY_MAP
,
144 string_equals
, string_hash
, NULL
, NULL
);
145 ASSERT (map1
!= NULL
);
148 map2
= gl_map_nx_create_empty (GL_HASH_MAP
,
149 string_equals
, string_hash
, NULL
, NULL
);
150 ASSERT (map2
!= NULL
);
152 check_all (map1
, map2
);
154 /* Initialize them. */
155 for (i
= 0; i
< initial_size
; i
++)
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
);
163 for (repeat
= 0; repeat
< 100000; repeat
++)
165 unsigned int operation
= RANDOM (3);
170 const char *key
= RANDOM_OBJECT ();
171 ASSERT (gl_map_get (map1
, key
) == gl_map_get (map2
, key
));
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
));
183 const char *key
= RANDOM_OBJECT ();
184 ASSERT (gl_map_remove (map1
, key
) == gl_map_remove (map2
, key
));
188 check_all (map1
, map2
);