1 /* Test of map data type implementation.
2 Copyright (C) 2006-2024 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_array_map.h"
27 #include "gl_array_list.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_list_t keys
, gl_list_t values
)
81 size_t n
= gl_map_size (map1
);
82 struct pair
*pairs_of_map1
= XNMALLOC (n
, struct pair
);
84 gl_map_iterator_t iter1
;
89 ASSERT (gl_list_size (keys
) == n
);
90 ASSERT (gl_list_size (values
) == n
);
91 iter1
= gl_map_iterator (map1
);
92 for (i
= 0; i
< n
; i
++)
94 ASSERT (gl_map_iterator_next (&iter1
, &key1
, &value1
));
95 pairs_of_map1
[i
].key
= key1
;
96 pairs_of_map1
[i
].value
= value1
;
98 ASSERT (!gl_map_iterator_next (&iter1
, &key1
, &value1
));
99 gl_map_iterator_free (&iter1
);
102 qsort (pairs_of_map1
, n
, sizeof (struct pair
), cmp_pairs_in_array
);
103 for (i
= 0; i
< n
; i
++)
105 ASSERT (pairs_of_map1
[i
].key
== gl_list_get_at (keys
, i
));
106 ASSERT (pairs_of_map1
[i
].value
== gl_list_get_at (values
, i
));
108 free (pairs_of_map1
);
112 check_all (gl_map_t map1
, gl_list_t keys
, gl_list_t values
)
114 check_equals (map1
, keys
, values
);
118 main (int argc
, char *argv
[])
124 /* Allow the user to provide a non-default random seed on the command line. */
126 srand (atoi (argv
[1]));
129 size_t initial_size
= RANDOM (20);
134 map1
= gl_map_nx_create_empty (GL_ARRAY_MAP
,
135 string_equals
, string_hash
, NULL
, NULL
);
136 ASSERT (map1
!= NULL
);
138 /* Create keys and values. */
139 keys
= gl_list_create_empty (GL_ARRAY_LIST
, NULL
, NULL
, NULL
, false);
140 values
= gl_list_create_empty (GL_ARRAY_LIST
, NULL
, NULL
, NULL
, false);
142 check_all (map1
, keys
, values
);
144 /* Initialize them. */
145 for (i
= 0; i
< initial_size
; i
++)
147 const char *key
= RANDOM_OBJECT ();
148 const char *value
= RANDOM_OBJECT ();
149 bool added
= gl_map_nx_put (map1
, key
, value
);
150 size_t index
= gl_sortedlist_indexof (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
151 ASSERT (added
== (index
== (size_t)(-1)));
154 gl_sortedlist_add (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
155 index
= gl_sortedlist_indexof (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
156 gl_list_add_at (values
, index
, value
);
159 gl_list_set_at (values
, index
, value
);
160 check_all (map1
, keys
, values
);
163 for (repeat
= 0; repeat
< 100000; repeat
++)
165 unsigned int operation
= RANDOM (3);
170 const char *key
= RANDOM_OBJECT ();
171 const void *ret
= gl_map_get (map1
, key
);
173 gl_sortedlist_indexof (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
175 == (index
!= (size_t)(-1) ? gl_list_get_at (values
, index
) : NULL
));
180 const char *key
= RANDOM_OBJECT ();
181 const char *value
= RANDOM_OBJECT ();
182 bool added
= gl_map_nx_put (map1
, key
, value
);
184 gl_sortedlist_indexof (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
185 ASSERT (added
== (index
== (size_t)(-1)));
188 gl_sortedlist_add (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
189 index
= gl_sortedlist_indexof (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
190 gl_list_add_at (values
, index
, value
);
193 gl_list_set_at (values
, index
, value
);
198 const char *key
= RANDOM_OBJECT ();
199 bool removed
= gl_map_remove (map1
, key
);
201 gl_sortedlist_indexof (keys
, (gl_listelement_compar_fn
)strcmp
, key
);
202 ASSERT (removed
== (index
!= (size_t)(-1)));
205 gl_list_remove_at (keys
, index
);
206 gl_list_remove_at (values
, index
);
211 check_all (map1
, keys
, values
);
216 gl_list_free (values
);
219 return test_exit_status
;