Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / tests / test_silchashtable.c
1 /* Hash table tests */
2
3 #include "silcincludes.h"
4
5 typedef struct entry_struct {
6   char name[8];
7   int val;
8 } *entry;
9
10 bool dump = FALSE;
11 bool 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 bool 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 bool 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     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 bool 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 bool 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     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 bool 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 bool 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
140 bool 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 bool 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     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 bool dump_table()
188 {
189   SilcHashTableList htl;
190   entry e;
191   char *name;
192   bool 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   bool success = FALSE;
211   int i;
212
213   if (argc > 1 && !strcmp(argv[1], "-d")) {
214     silc_debug = 1;
215     silc_debug_hexdump = 1;
216     silc_log_set_debug_string("*table*");
217   }
218
219   if (argc > 1 && !strcmp(argv[1], "-D")) {
220     silc_debug = 1;
221     dump = TRUE;
222     silc_log_set_debug_string("*table*");
223   }
224
225   if (!alloc_table())
226     goto err;
227   if (!dump_table())
228     goto err;
229   if (!delete_table_with_list())
230     goto err;
231
232   count = 1387;
233   auto_rehash = FALSE;
234   if (!alloc_table())
235     goto err;
236   if (!dump_table())
237     goto err;
238   SILC_LOG_DEBUG(("rehash"));
239   silc_hash_table_rehash(t, 0);
240   SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
241   SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
242   if (!delete_table_with_list())
243     goto err;
244
245   count = 999;
246   auto_rehash = TRUE;
247   if (!alloc_table())
248     goto err;
249   count = 3999;
250   if (!add_entries())
251     goto err;
252   SILC_LOG_DEBUG(("rehash"));
253   silc_hash_table_rehash(t, 0);
254   SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
255   SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
256   if (!del_entries_with_list())
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   count = 999;
263   if (!add_entries())
264     goto err;
265   /* Adding duplicates */
266   for (i = 0; i < 30; i++) {
267     count = 50;
268     if (!add_entries())
269       goto err;
270   }
271   count = 700;
272   if (!find_entries())
273     goto err;
274   count = 500;
275   if (!del_n_entries_foreach())
276     goto err;
277   count = 999;
278   if (!add_entries())
279     goto err;
280   count = 700;
281   if (!find_entries())
282     goto err;
283   if (!dump_table())
284     goto err;
285   if (!del_entries_foreach())
286     goto err;
287   if (!delete_table_with_list())
288     goto err;
289
290   success = TRUE;
291
292  err:
293   SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
294   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
295
296   return success;
297 }