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