Added silc_getopt.
[silc.git] / lib / silcutil / tests / test_silchashtable.c
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
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
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
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
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
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
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
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
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
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(NULL, 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
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
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
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
208 int main(int argc, char **argv)
209 {
210   SilcBool success = FALSE;
211   SilcGetOptStruct op = SILC_GETOPT_INIT;
212   int opt;
213   int i;
214
215   while ((opt = silc_getopt(argc, argv, "de::D", &op)) != -1) {
216     switch (opt) {
217       case 'd':
218         silc_log_debug(TRUE);
219         silc_log_debug_hexdump(TRUE);
220         silc_log_quick(TRUE);
221         silc_log_set_debug_string("*table*,*errno*");
222         break;
223
224       case 'D':
225         silc_log_debug(TRUE);
226         dump = TRUE;
227         silc_log_set_debug_string("*table*,*errno*");
228         break;
229
230       case 'e':
231         silc_log_debug(TRUE);
232         fprintf(stderr, "%s\n", op.opt_arg);
233         if (op.opt_arg) {
234           dump = TRUE;
235           silc_log_set_debug_string(op.opt_arg);
236         }
237         break;
238
239       default:
240         exit(1);
241         break;
242     }
243   }
244
245   if (!alloc_table())
246     goto err;
247   if (!dump_table())
248     goto err;
249   if (!delete_table_with_list())
250     goto err;
251
252   count = 1387;
253   auto_rehash = FALSE;
254   if (!alloc_table())
255     goto err;
256   if (!dump_table())
257     goto err;
258   SILC_LOG_DEBUG(("rehash"));
259   silc_hash_table_rehash(t, 0);
260   SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
261   SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
262   if (!delete_table_with_list())
263     goto err;
264
265   count = 999;
266   auto_rehash = TRUE;
267   if (!alloc_table())
268     goto err;
269   count = 17999;
270   if (!add_entries())
271     goto err;
272   SILC_LOG_DEBUG(("rehash"));
273   silc_hash_table_rehash(t, 0);
274   SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
275   SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
276   if (!del_entries_with_list())
277     goto err;
278   SILC_LOG_DEBUG(("rehash"));
279   silc_hash_table_rehash(t, 0);
280   SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
281   SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
282   count = 999;
283   if (!add_entries())
284     goto err;
285   /* Adding duplicates */
286   for (i = 0; i < 30; i++) {
287     count = 50;
288     if (!add_entries())
289       goto err;
290   }
291   count = 700;
292   if (!find_entries())
293     goto err;
294   count = 500;
295   if (!del_n_entries_foreach())
296     goto err;
297   count = 999;
298   if (!add_entries())
299     goto err;
300   count = 700;
301   if (!find_entries())
302     goto err;
303   if (!dump_table())
304     goto err;
305   if (!del_entries_foreach())
306     goto err;
307   if (!delete_table_with_list())
308     goto err;
309
310   success = TRUE;
311
312  err:
313   SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
314   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
315
316   return success;
317 }