d23bd34a946b4f5be9c27b4f34db945cbd39e9f2
[ircu2.10.12-pk.git] / libs / dbprim / tests / t_ht_resize.c
1 /*
2 ** Copyright (C) 2002 by Kevin L. Mitchell <klmitch@mit.edu>
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Library General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 ** Library General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Library General Public
15 ** License along with this library; if not, write to the Free
16 ** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17 ** MA 02111-1307, USA
18 **
19 ** @(#)$Id$
20 */
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include "dbprim.h"
26 #include "dbprim_int.h"
27
28 #define TABLE0  (void *)0x76543210
29
30 #define OBJECT0 (void *)0x01234567
31 #define OBJECT1 (void *)0x12345678
32 #define OBJECT2 (void *)0x23456789
33 #define OBJECT3 (void *)0x3456789a
34 #define OBJECT4 (void *)0x456789ab
35 #define OBJECT5 (void *)0x56789abc
36 #define OBJECT6 (void *)0x6789abcd
37 #define OBJECT7 (void *)0x789abcde
38
39 #define DEADINT 0xdeadbeef
40 #define DEADPTR (void *)0xdeadbeef
41
42 struct itercheck {
43   hash_table_t *ent_table;
44   hash_entry_t *ent_array;
45   unsigned int  ent_mask;
46 };
47
48 #define BIT(n)  (1 << (n))
49 #define BITMASK 0x000000ff
50
51 /* Check return value of add operation and report PASS/FAIL */
52 static void
53 check_result(unsigned long result, unsigned long expected, char *test,
54              char *info, int die)
55 {
56   if (result != expected) {
57     printf("FAIL/%s:%s incorrectly returned %lu (expected %lu)\n", test, info,
58            result, expected);
59     if (die)
60       exit(0);
61   } else
62     printf("PASS/%s:%s correctly returned %lu\n", test, info, result);
63 }
64
65 static unsigned long
66 check_func(hash_table_t *table, db_key_t *key)
67 {
68   return dk_len(key);
69 }
70
71 static unsigned long
72 check_comp(hash_table_t *table, db_key_t *key1, db_key_t *key2)
73 {
74   return (!(dk_len(key1) == dk_len(key2) && dk_key(key1) == dk_key(key2)));
75 }
76
77 static void
78 check_modulus(hash_table_t *tab, unsigned long mod, char *test, char *comment)
79 {
80   if (ht_modulus(tab) != mod) {
81     printf("FAIL/%s_mod:%s (modulus %ld, supposed to be %ld)\n", test, comment,
82            ht_modulus(tab), mod);
83     exit(0);
84   } else
85     printf("PASS/%s_mod:%s (modulus %ld)\n", test, comment, mod);
86 }
87
88 static unsigned long
89 check_iter(hash_table_t *table, hash_entry_t *ent, void *extra)
90 {
91   struct itercheck *itcheck;
92
93   itcheck = extra;
94
95   /* OK, verify that the hash table is the same as the one we expect */
96   if (table != itcheck->ent_table) {
97     printf("FAIL/ht_resize_functab_e%d:Hash tables do not match\n",
98            dk_len(he_key(ent)));
99     exit(0);
100   } else
101     printf("PASS/ht_resize_functab_e%d:Hash tables match\n",
102            dk_len(he_key(ent)));
103
104   /* Now verify that everything matches up... */
105   if (ent != &itcheck->ent_array[dk_len(he_key(ent))]) {
106     printf("FAIL/ht_resize_funcent_e%d:Entries do not match\n",
107            dk_len(he_key(ent)));
108     exit(0);
109   } else
110     printf("PASS/ht_resize_funcent_e%d:Entries match\n", dk_len(he_key(ent)));
111
112   /* Finally, set the visited bitmask */
113   itcheck->ent_mask |= BIT(dk_len(he_key(ent)));
114
115   return 0;
116 }
117
118 static unsigned long
119 do_rsize_check(hash_table_t *table, unsigned long new_mod, char *test,
120                unsigned long err)
121 {
122   check_modulus(table, 11, test,
123                 "Check that table calls callback before resize");
124   if (new_mod != 3) {
125     printf("FAIL/%s_newmod:Check that resize callback is called with new "
126            "size failed: new size %ld, should be 3\n", test, new_mod);
127     exit(0);
128   } else
129     printf("PASS/%s_newmod:Check that resize callback is called with new "
130            "size (%ld)\n", test, new_mod);
131
132   return err;
133 }
134
135 static unsigned long
136 check_rsize_err(hash_table_t *table, unsigned long new_mod)
137 {
138   return do_rsize_check(table, new_mod, "ht_resize_callerr", EINVAL);
139 }
140
141 static unsigned long
142 check_rsize(hash_table_t *table, unsigned long new_mod)
143 {
144   return do_rsize_check(table, new_mod, "ht_resize_callback", 0);
145 }
146
147 int
148 main(int argc, char **argv)
149 {
150   int i;
151   hash_table_t table[] = { /* some tables to operate on */
152     HASH_TABLE_INIT(0, check_func, check_comp, 0, TABLE0),
153     { DEADINT, DEADINT, DEADINT, DEADINT, DEADINT, DEADINT, DEADPTR,
154       (hash_func_t)DEADPTR, (hash_comp_t)DEADPTR, (hash_resize_t)DEADPTR,
155       DEADPTR } /* table[1] */
156   };
157   hash_entry_t entry[] = { /* some entries to operate on */
158     HASH_ENTRY_INIT(OBJECT0),
159     HASH_ENTRY_INIT(OBJECT1),
160     HASH_ENTRY_INIT(OBJECT2),
161     HASH_ENTRY_INIT(OBJECT3),
162     HASH_ENTRY_INIT(OBJECT4),
163     HASH_ENTRY_INIT(OBJECT5),
164     HASH_ENTRY_INIT(OBJECT6),
165     HASH_ENTRY_INIT(OBJECT7),
166     { DEADINT, { DEADINT, DEADPTR, DEADPTR, DEADPTR, DEADPTR, DEADINT },
167       DEADPTR, DEADINT, { DEADPTR, DEADINT }, DEADPTR } /* entry[7] */
168   };
169   db_key_t key[] = { /* some keys... */
170     DB_KEY_INIT("obj0", 0),
171     DB_KEY_INIT("obj1", 1),
172     DB_KEY_INIT("obj2", 2),
173     DB_KEY_INIT("obj3", 3),
174     DB_KEY_INIT("obj4", 4),
175     DB_KEY_INIT("obj5", 5),
176     DB_KEY_INIT("obj6", 6),
177     DB_KEY_INIT("obj7", 7)
178   };
179   struct itercheck itcheck = { 0, 0, 0 };
180
181   /* initialize the tables with a size */
182   if (ht_init(&table[0], 0, check_func, check_comp, 0, TABLE0, 3))
183     return -1; /* failed to initialize test */
184
185   /* Add some entries to various hash tables */
186   for (i = 0; i < 8; i++)
187     if (ht_add(&table[0], &entry[i], &key[i]))
188       return -1; /* failed to initialize test */
189
190   /* Check handling of bad arguments */
191   check_result(ht_resize(0, 0), DB_ERR_BADARGS, "ht_resize_noargs",
192                "ht_resize() with no valid arguments", 0);
193   check_result(ht_resize(&table[1], 0), DB_ERR_BADARGS, "ht_resize_badtable",
194                "ht_resize() with bad table", 0);
195
196   /* Freeze the table temporarily */
197   ht_flags(&table[0]) |= HASH_FLAG_FREEZE;
198   /* check if frozen tables are excluded */
199   check_result(ht_resize(&table[0], 0), DB_ERR_FROZEN, "ht_resize_frozen",
200                "ht_resize() on frozen table", 1);
201   /* Unfreeze the table */
202   ht_flags(&table[0]) &= ~HASH_FLAG_FREEZE;
203
204   /* OK, now try resizing to current size */
205   check_result(ht_resize(&table[0], 0), 0, "ht_resize_current",
206                "ht_resize() to current table count", 1);
207   check_modulus(&table[0], 11, "ht_resize_current",
208                 "Table modulus after ht_resize()");
209
210   /* Next, try shrinking */
211   check_result(ht_resize(&table[0], 4), 0, "ht_resize_shrink",
212                "ht_resize() to shrink table", 1);
213   check_modulus(&table[0], 5, "ht_resize_shrink",
214                 "Table modulus after ht_resize() to shrink");
215
216   /* Now try growing */
217   check_result(ht_resize(&table[0], 18), 0, "ht_resize_grow",
218                "ht_resize() to grow table", 1);
219   check_modulus(&table[0], 19, "ht_resize_grow",
220                 "Table modulus after ht_grow() to grow");
221
222   /* Iterate through the table and make sure everything's there */
223   itcheck.ent_table = &table[0];
224   itcheck.ent_array = entry;
225   itcheck.ent_mask = 0;
226   check_result(ht_iter(&table[0], check_iter, &itcheck), 0,
227                "ht_resize_elemchk", "Check that hash table is valid", 1);
228
229   /* Did it iterate through them all? */
230   if (itcheck.ent_mask == BITMASK)
231     printf("PASS/ht_resize_funcmask:ht_resize() retained all items\n");
232   else {
233     printf("FAIL/ht_resize_funcmask:ht_resize() retained only items in "
234            "bitmask 0x%02x\n", itcheck.ent_mask);
235     return 0;
236   }
237
238   /* Set the table to autoshrink */
239   ht_flags(&table[0]) |= HASH_FLAG_AUTOSHRINK;
240   check_result(ht_remove(&table[0], &entry[7]), 0, "ht_remove_autoshrink",
241                "Check to see that ht_remove() on autoshrink shrinks table", 1);
242
243   /* Make certain table has been properly resized */
244   check_modulus(&table[0], 11, "ht_remove_autoshrink",
245                 "Check that ht_remove() shrank table");
246
247   /* Set the resize callback */
248   ht_rsize(&table[0]) = check_rsize_err;
249
250   /* Check to make sure we got the expected error return value */
251   check_result(ht_resize(&table[0], 3), EINVAL, "ht_resize_callerr",
252                "Check that resize callback's error code is returned", 1);
253
254   /* Set the resize callback to something that'll work */
255   ht_rsize(&table[0]) = check_rsize;
256
257   /* Shrink the table very small for the next step */
258   check_result(ht_resize(&table[0], 3), 0, "ht_resize_prep",
259                "Prepare for auto-grow test", 1);
260   /* Make certain table has been properly resized */
261   check_modulus(&table[0], 3, "ht_resize_prep",
262                 "Check that ht_resize() shrank table");
263
264   /* Now clear the resize callback */
265   ht_rsize(&table[0]) = 0;
266
267   /* Now try to autogrow */
268   ht_flags(&table[0]) |= HASH_FLAG_AUTOGROW;
269   check_result(ht_add(&table[0], &entry[7], &key[7]), 0, "ht_add_autogrow",
270                "Check to see that ht_add() on autogrow grows table", 1);
271
272   /* Make certain table has been properly resized */
273   check_modulus(&table[0], 11, "ht_add_autogrow",
274                 "Check that ht_add() grew table");
275
276   return 0;
277 }