Mercurial > gnulib
annotate tests/test-hash_map.c @ 40174:b76c7bdde2bf
*-map tests: Fix compilation error.
* tests/test-array_map.c: Include <limits.h>, for CHAR_BIT.
* tests/test-hash_map.c: Likewise.
* tests/test-linkedhash_map.c: Likewise.
author | Colin Watson <cjwatson@debian.org> |
---|---|
date | Sat, 02 Feb 2019 16:12:09 +0100 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
40024 | 1 /* Test of map data type implementation. |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
40024
diff
changeset
|
2 Copyright (C) 2006-2019 Free Software Foundation, Inc. |
40024 | 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_hash_map.h" | |
21 | |
40174
b76c7bdde2bf
*-map tests: Fix compilation error.
Colin Watson <cjwatson@debian.org>
parents:
40057
diff
changeset
|
22 #include <limits.h> |
40024 | 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) | |
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) | |
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) | |
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) | |
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) | |
124 { | |
125 check_equals (map1, map2); | |
126 } | |
127 | |
128 int | |
129 main (int argc, char *argv[]) | |
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_HASH_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 } |