Line data Source code
1 : #include "passgen/container/hashmap.h"
2 : #include "tests.h"
3 : #include <stdlib.h>
4 : #include <string.h>
5 :
6 1 : test_result test_hashmap_init(void) {
7 : passgen_hashmap map;
8 1 : passgen_hashmap_init(&map, NULL);
9 1 : passgen_hashmap_free(&map);
10 1 : return test_ok;
11 : }
12 :
13 1 : test_result test_hashmap_context_utf8(void) {
14 : passgen_hashmap map;
15 1 : passgen_hashmap_init(&map, &passgen_hashmap_context_utf8);
16 :
17 1 : const char *key1 = "hello";
18 1 : const char *key2 = "hola";
19 :
20 1 : assert(passgen_hashmap_context_utf8.equal(&map, key1, key1));
21 1 : assert(passgen_hashmap_context_utf8.equal(&map, key2, key2));
22 1 : assert(!passgen_hashmap_context_utf8.equal(&map, key1, key2));
23 :
24 1 : assert_eq(
25 : passgen_hashmap_context_utf8.hash(&map, key1, true),
26 : 0xf6f0cd43722c7cfe);
27 1 : assert_eq(
28 : passgen_hashmap_context_utf8.hash(&map, key1, false),
29 : 0x438bcb516e4d4abf);
30 :
31 1 : assert_eq(
32 : passgen_hashmap_context_utf8.hash(&map, key2, true),
33 : 0xcb99aa476d12f348);
34 1 : assert_eq(
35 : passgen_hashmap_context_utf8.hash(&map, key2, false),
36 : 0xef7ec81d7aa533ea);
37 :
38 1 : passgen_hashmap_free(&map);
39 :
40 1 : return test_ok;
41 : }
42 :
43 1 : test_result test_hashmap_context_utf32(void) {
44 : passgen_hashmap map;
45 1 : passgen_hashmap_init(&map, &passgen_hashmap_context_utf32);
46 :
47 1 : uint32_t key1[] = {'h', 'e', 'l', 'l', 'o', 0};
48 1 : uint32_t key2[] = {'h', 'o', 'l', 'a', 0};
49 :
50 1 : assert(passgen_hashmap_context_utf32.equal(&map, &key1[0], &key1[0]));
51 1 : assert(passgen_hashmap_context_utf32.equal(&map, &key2[0], &key2[0]));
52 1 : assert(!passgen_hashmap_context_utf32.equal(&map, &key1[0], &key2[0]));
53 :
54 1 : assert_eq(
55 : passgen_hashmap_context_utf32.hash(&map, &key1[0], true),
56 : 0x4b9a41e6925a46ad);
57 1 : assert_eq(
58 : passgen_hashmap_context_utf32.hash(&map, &key1[0], false),
59 : 0x6ce43ac01a6144b8);
60 :
61 1 : assert_eq(
62 : passgen_hashmap_context_utf32.hash(&map, &key2[0], true),
63 : 0xdefab330a5dcde19);
64 1 : assert_eq(
65 : passgen_hashmap_context_utf32.hash(&map, &key2[0], false),
66 : 0x45168f9b31b7e7bd);
67 :
68 1 : passgen_hashmap_free(&map);
69 :
70 1 : return test_ok;
71 : }
72 :
73 1 : test_result test_hashmap_insert_utf32(void) {
74 : passgen_hashmap map;
75 : passgen_hashmap_entry entry;
76 :
77 1 : passgen_hashmap_init(&map, &passgen_hashmap_context_utf32);
78 :
79 1 : uint32_t key1[] = {'h', 'e', 'l', 'l', 'o', 0};
80 : int value1;
81 1 : entry = passgen_hashmap_insert(&map, &key1, &value1);
82 1 : assert_eq(entry.key, NULL);
83 1 : assert_eq(entry.value, NULL);
84 1 : assert_eq(map.len, 1);
85 1 : assert_eq(passgen_hashmap_lookup(&map, &key1)->value, &value1);
86 :
87 1 : uint32_t key2[] = {'h', 'o', 'l', 'a', 0};
88 : int value2;
89 1 : entry = passgen_hashmap_insert(&map, &key2, &value2);
90 1 : assert_eq(map.len, 2);
91 1 : assert_eq(entry.key, NULL);
92 1 : assert_eq(entry.value, NULL);
93 1 : assert_eq(passgen_hashmap_lookup(&map, &key1)->value, &value1);
94 1 : assert_eq(passgen_hashmap_lookup(&map, &key2)->value, &value2);
95 :
96 1 : passgen_hashmap_free(&map);
97 :
98 1 : return test_ok;
99 : }
100 :
101 1 : test_result test_hashmap_insert_utf8(void) {
102 : passgen_hashmap map;
103 1 : passgen_hashmap_init(&map, NULL);
104 :
105 1 : int value_a = 4, value_b = 7;
106 :
107 1 : passgen_hashmap_insert(&map, "hello", &value_a);
108 1 : assert_eq(map.len, 1);
109 1 : passgen_hashmap_insert(&map, "world", &value_b);
110 1 : assert_eq(map.len, 2);
111 :
112 : passgen_hashmap_entry *entry;
113 1 : entry = passgen_hashmap_lookup(&map, "hello");
114 1 : assert(entry);
115 1 : assert_eq(entry->value, &value_a);
116 :
117 1 : entry = passgen_hashmap_lookup(&map, "world");
118 1 : assert(entry);
119 1 : assert_eq(entry->value, &value_b);
120 :
121 1 : entry = passgen_hashmap_lookup(&map, "other");
122 1 : assert(!entry);
123 :
124 1 : passgen_hashmap_free(&map);
125 1 : return test_ok;
126 : }
127 :
128 1 : test_result test_hashmap_insert_many(void) {
129 : passgen_hashmap map;
130 1 : passgen_hashmap_init(&map, NULL);
131 1 : size_t insert_max = 10000;
132 :
133 : // insert large amount of items
134 10001 : for(size_t i = 0; i < insert_max; i++) {
135 10000 : assert_eq(map.len, i);
136 10000 : char *key = malloc(32);
137 10000 : size_t *value = malloc(sizeof(size_t));
138 10000 : *value = i;
139 10000 : snprintf(key, 32, "%zu", i);
140 10000 : passgen_hashmap_insert(&map, key, value);
141 :
142 : // fill factor is how many percent of slots are used. we want this
143 : // to be high.
144 10000 : float fill = map.len * 100.0 / (double) map.capacity;
145 10000 : assert(fill > 3.0);
146 : }
147 :
148 : // retrieve all items
149 10001 : for(size_t i = 0; i < insert_max; i++) {
150 : char key[32];
151 10000 : snprintf(key, 32, "%zu", i);
152 10000 : passgen_hashmap_entry *entry = passgen_hashmap_lookup(&map, key);
153 10000 : assert(entry);
154 10000 : size_t *value = entry->value;
155 10000 : assert_eq(*value, i);
156 : }
157 :
158 : // release memory
159 1 : passgen_hashmap_foreach(&map, NULL, passgen_hashmap_entry_free);
160 :
161 1 : passgen_hashmap_free(&map);
162 1 : return test_ok;
163 : }
164 :
165 1 : test_result test_hashmap_remove(void) {
166 : passgen_hashmap map;
167 1 : passgen_hashmap_init(&map, NULL);
168 :
169 1 : int value_a = 4, value_b = 7;
170 :
171 1 : passgen_hashmap_insert(&map, "hello", &value_a);
172 1 : passgen_hashmap_insert(&map, "world", &value_b);
173 1 : assert_eq(map.len, 2);
174 :
175 1 : assert(passgen_hashmap_lookup(&map, "hello"));
176 1 : assert(passgen_hashmap_lookup(&map, "world"));
177 1 : assert(!passgen_hashmap_lookup(&map, "other"));
178 :
179 : passgen_hashmap_entry entry;
180 1 : entry = passgen_hashmap_remove(&map, "hello");
181 1 : assert_eq(map.len, 1);
182 1 : assert(entry.key);
183 1 : assert_eq(entry.value, &value_a);
184 1 : assert_streq(entry.key, "hello");
185 :
186 1 : assert(!passgen_hashmap_lookup(&map, "hello"));
187 1 : assert(passgen_hashmap_lookup(&map, "world"));
188 1 : assert(!passgen_hashmap_lookup(&map, "other"));
189 :
190 1 : entry = passgen_hashmap_remove(&map, "world");
191 1 : assert_eq(map.len, 0);
192 1 : assert(entry.key);
193 1 : assert_eq(entry.value, &value_b);
194 1 : assert_streq(entry.key, "world");
195 :
196 1 : assert(!passgen_hashmap_lookup(&map, "hello"));
197 1 : assert(!passgen_hashmap_lookup(&map, "world"));
198 1 : assert(!passgen_hashmap_lookup(&map, "other"));
199 :
200 1 : passgen_hashmap_free(&map);
201 1 : return test_ok;
202 : }
203 :
204 1 : test_result test_hashmap_lookup_empty(void) {
205 : passgen_hashmap map;
206 1 : passgen_hashmap_init(&map, NULL);
207 :
208 1 : passgen_hashmap_entry *entry = passgen_hashmap_lookup(&map, "test");
209 1 : assert(!entry);
210 :
211 1 : passgen_hashmap_free(&map);
212 1 : return test_ok;
213 : }
214 :
215 1 : int function_fails(void *data, passgen_hashmap_entry *entry) {
216 : (void) data;
217 : (void) entry;
218 1 : return 7;
219 : }
220 :
221 5 : int free_value(void *data, passgen_hashmap_entry *entry) {
222 : (void) data;
223 5 : free(entry->value);
224 5 : return 0;
225 : }
226 :
227 1 : test_result test_hashmap_foreach(void) {
228 : passgen_hashmap map;
229 1 : passgen_hashmap_init(&map, NULL);
230 :
231 1 : passgen_hashmap_insert(&map, "alpha", malloc(255));
232 1 : passgen_hashmap_insert(&map, "beta", malloc(255));
233 1 : passgen_hashmap_insert(&map, "gamma", malloc(255));
234 1 : passgen_hashmap_insert(&map, "delta", malloc(255));
235 1 : passgen_hashmap_insert(&map, "epsilon", malloc(255));
236 :
237 1 : assert_eq(passgen_hashmap_foreach(&map, NULL, function_fails), 7);
238 1 : assert_eq(passgen_hashmap_foreach(&map, NULL, free_value), 0);
239 :
240 1 : passgen_hashmap_free(&map);
241 1 : return test_ok;
242 : }
|