1 /* Hash table tests */
2
3 #include "silc.h"
4
5 typedef struct entry_struct {
6 char name[8];
7 int val;
8 } *entry;
9
10 SilcBool dump = FALSE;
11 SilcBool auto_rehash = TRUE;
12 int count = 2000;
13 SilcHashTable t = NULL;
14
hash_entry(void * key,void * user_context)15 SilcUInt32 hash_entry(void *key, void *user_context)
16 {
17 entry e = key;
18 return e->val + silc_hash_string(e->name, NULL);
19 }
20
hash_compare(void * key1,void * key2,void * user_context)21 SilcBool hash_compare(void *key1, void *key2, void *user_context)
22 {
23 entry e = key1;
24 entry e2 = key2;
25 if (e->val == e2->val && !strcmp(e->name, e2->name))
26 return TRUE;
27 return FALSE;
28 }
29
hash_destructor(void * key,void * context,void * user_context)30 void hash_destructor(void *key, void *context, void *user_context)
31 {
32 entry e = key;
33 char *name = context;
34 if (dump)
35 SILC_LOG_DEBUG(("e=%p, e->val=%d, e->name=%s, context=%s",
36 e, e->val, e->name, name));
37 memset(e, 'F', sizeof(*e));
38 silc_free(e);
39 }
40
add_entries()41 SilcBool add_entries()
42 {
43 entry e;
44 int i;
45
46 SILC_LOG_DEBUG(("Adding %d entries", count));
47
48 for (i = 0; i < count; i++) {
49 e = silc_calloc(1, sizeof(*e));
50 if (!e)
51 return FALSE;
52 silc_snprintf(e->name, sizeof(e->name), "%d", i);
53 e->val = i;
54
55 silc_hash_table_add(t, (void *)e, (void *)e->name);
56 }
57
58 SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
59
60 return TRUE;
61 }
62
del_entries_with_list()63 SilcBool del_entries_with_list()
64 {
65 SilcHashTableList htl;
66 entry e;
67 char *name;
68
69 SILC_LOG_DEBUG(("Deleting entries with SilcHashTableList"));
70
71 silc_hash_table_list(t, &htl);
72 while (silc_hash_table_get(&htl, (void **)&e, (void **)&name)) {
73 if (!silc_hash_table_del(t, e))
74 return FALSE;
75 }
76 silc_hash_table_list_reset(&htl);
77
78 SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
79
80 return TRUE;
81 }
82
del_foreach(void * key,void * context,void * user_context)83 void del_foreach(void *key, void *context, void *user_context)
84 {
85 entry e = key;
86 char *name = context;
87 if (dump)
88 SILC_LOG_DEBUG(("del_foreach found e=%p, e->val=%d, e->name=%s, context=%s",
89 e, e->val, e->name, name));
90 silc_hash_table_del(t, key);
91 }
92
del_n_entries_foreach()93 SilcBool del_n_entries_foreach()
94 {
95 struct entry_struct f;
96 int i;
97
98 SILC_LOG_DEBUG(("Deleting keys 0-%d with foreach", count));
99
100 for (i = 0; i < count; i++) {
101 memset(&f, 0, sizeof(f));
102 silc_snprintf(f.name, sizeof(f.name), "%d", i);
103 f.val = i;
104
105 silc_hash_table_find_foreach(t, &f, del_foreach, NULL);
106 }
107
108 return TRUE;
109 }
110
del_entries_foreach()111 SilcBool del_entries_foreach()
112 {
113 SILC_LOG_DEBUG(("Deleting all entries with foreach"));
114 silc_hash_table_foreach(t, del_foreach, NULL);
115 return TRUE;
116 }
117
alloc_table()118 SilcBool alloc_table()
119 {
120 SILC_LOG_DEBUG(("Allocating hash table with %d entries (%s)",
121 count, auto_rehash ? "auto rehash" : "no auto rehash"));
122
123 t = silc_hash_table_alloc(0, hash_entry, NULL,
124 hash_compare, NULL,
125 hash_destructor, NULL, auto_rehash);
126
127 if (!add_entries())
128 return FALSE;
129
130 SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
131
132 if (silc_hash_table_count(t) != count) {
133 SILC_LOG_DEBUG(("Wrong table count %d", count));
134 return FALSE;
135 }
136
137 return TRUE;
138 }
139
delete_table_with_list()140 SilcBool delete_table_with_list()
141 {
142
143 SILC_LOG_DEBUG(("Deleting entries with SilcHashTableList"));
144
145 if (!del_entries_with_list())
146 return FALSE;
147
148 SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
149
150 if (silc_hash_table_count(t) != 0) {
151 SILC_LOG_DEBUG(("Wrong table count %d != 0", count));
152 return FALSE;
153 }
154
155 silc_hash_table_free(t);
156 t = NULL;
157
158 return TRUE;
159 }
160
find_entries()161 SilcBool find_entries()
162 {
163 struct entry_struct f;
164 entry e;
165 char *name;
166 int i;
167
168 SILC_LOG_DEBUG(("Finding %d entries", count));
169
170 for (i = 0; i < count; i++) {
171 memset(&f, 0, sizeof(f));
172 silc_snprintf(f.name, sizeof(f.name), "%d", i);
173 f.val = i;
174
175 /* Find */
176 if (!silc_hash_table_find(t, &f, (void **)&e, (void **)&name))
177 return FALSE;
178
179 /* Find itself with context */
180 if (!silc_hash_table_find_by_context(t, e, e->name, NULL))
181 return FALSE;
182 }
183
184 return TRUE;
185 }
186
dump_table()187 SilcBool dump_table()
188 {
189 SilcHashTableList htl;
190 entry e;
191 char *name;
192 SilcBool dumpped = FALSE;
193
194 SILC_LOG_DEBUG(("Dumping hash table entries"));
195
196 silc_hash_table_list(t, &htl);
197 while (silc_hash_table_get(&htl, (void **)&e, (void **)&name)) {
198 dumpped = TRUE;
199 if (dump)
200 SILC_LOG_DEBUG(("e=%p, e->val=%d, e->name=%s, context=%s",
201 e, e->val, e->name, name));
202 }
203 silc_hash_table_list_reset(&htl);
204
205 return dumpped;
206 }
207
main(int argc,char ** argv)208 int main(int argc, char **argv)
209 {
210 SilcBool success = FALSE;
211 int i;
212
213 if (argc > 1 && !strcmp(argv[1], "-d")) {
214 silc_log_debug(TRUE);
215 silc_log_debug_hexdump(TRUE);
216 silc_log_quick(TRUE);
217 silc_log_set_debug_string("*table*");
218 }
219
220 if (argc > 1 && !strcmp(argv[1], "-D")) {
221 silc_log_debug(TRUE);
222 dump = TRUE;
223 silc_log_set_debug_string("*table*");
224 }
225
226 if (!alloc_table())
227 goto err;
228 if (!dump_table())
229 goto err;
230 if (!delete_table_with_list())
231 goto err;
232
233 count = 1387;
234 auto_rehash = FALSE;
235 if (!alloc_table())
236 goto err;
237 if (!dump_table())
238 goto err;
239 SILC_LOG_DEBUG(("rehash"));
240 silc_hash_table_rehash(t, 0);
241 SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
242 SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
243 if (!delete_table_with_list())
244 goto err;
245
246 count = 999;
247 auto_rehash = TRUE;
248 if (!alloc_table())
249 goto err;
250 count = 17999;
251 if (!add_entries())
252 goto err;
253 SILC_LOG_DEBUG(("rehash"));
254 silc_hash_table_rehash(t, 0);
255 SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
256 SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
257 if (!del_entries_with_list())
258 goto err;
259 SILC_LOG_DEBUG(("rehash"));
260 silc_hash_table_rehash(t, 0);
261 SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
262 SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
263 count = 999;
264 if (!add_entries())
265 goto err;
266 /* Adding duplicates */
267 for (i = 0; i < 30; i++) {
268 count = 50;
269 if (!add_entries())
270 goto err;
271 }
272 count = 700;
273 if (!find_entries())
274 goto err;
275 count = 500;
276 if (!del_n_entries_foreach())
277 goto err;
278 count = 999;
279 if (!add_entries())
280 goto err;
281 count = 700;
282 if (!find_entries())
283 goto err;
284 if (!dump_table())
285 goto err;
286 if (!del_entries_foreach())
287 goto err;
288 if (!delete_table_with_list())
289 goto err;
290
291 success = TRUE;
292
293 err:
294 SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
295 fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
296
297 return success;
298 }
299