Added preliminary Symbian support.
[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(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   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 }