1 1.1 christos /* 2 1.1 christos * testcode/unitlruhash.c - unit test for lruhash table. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * This software is open source. 7 1.1 christos * 8 1.1 christos * Redistribution and use in source and binary forms, with or without 9 1.1 christos * modification, are permitted provided that the following conditions 10 1.1 christos * are met: 11 1.1 christos * 12 1.1 christos * Redistributions of source code must retain the above copyright notice, 13 1.1 christos * this list of conditions and the following disclaimer. 14 1.1 christos * 15 1.1 christos * Redistributions in binary form must reproduce the above copyright notice, 16 1.1 christos * this list of conditions and the following disclaimer in the documentation 17 1.1 christos * and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * Neither the name of the NLNET LABS nor the names of its contributors may 20 1.1 christos * be used to endorse or promote products derived from this software without 21 1.1 christos * specific prior written permission. 22 1.1 christos * 23 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 1.1 christos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 1.1 christos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 1.1 christos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 1.1 christos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 1.1 christos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 1.1 christos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 christos * 35 1.1 christos */ 36 1.1 christos /** 37 1.1 christos * \file 38 1.1 christos * Tests the locking LRU keeping hash table implementation. 39 1.1 christos */ 40 1.1 christos 41 1.1 christos #include "config.h" 42 1.1 christos #include "testcode/unitmain.h" 43 1.1 christos #include "util/log.h" 44 1.1 christos #include "util/storage/lruhash.h" 45 1.1 christos #include "util/storage/slabhash.h" /* for the test structures */ 46 1.1 christos 47 1.1 christos /** use this type for the lruhash test key */ 48 1.1.1.2 christos typedef struct slabhash_testkey testkey_type; 49 1.1 christos /** use this type for the lruhash test data */ 50 1.1.1.2 christos typedef struct slabhash_testdata testdata_type; 51 1.1 christos 52 1.1 christos /** delete key */ 53 1.1 christos static void delkey(struct slabhash_testkey* k) { 54 1.1 christos lock_rw_destroy(&k->entry.lock); free(k);} 55 1.1 christos /** delete data */ 56 1.1 christos static void deldata(struct slabhash_testdata* d) {free(d);} 57 1.1 christos 58 1.1 christos /** hash func, very bad to improve collisions */ 59 1.1.1.2 christos static hashvalue_type myhash(int id) {return (hashvalue_type)id & 0x0f;} 60 1.1 christos /** allocate new key, fill in hash */ 61 1.1.1.2 christos static testkey_type* newkey(int id) { 62 1.1.1.2 christos testkey_type* k = (testkey_type*)calloc(1, sizeof(testkey_type)); 63 1.1 christos if(!k) fatal_exit("out of memory"); 64 1.1 christos k->id = id; 65 1.1 christos k->entry.hash = myhash(id); 66 1.1 christos k->entry.key = k; 67 1.1 christos lock_rw_init(&k->entry.lock); 68 1.1 christos return k; 69 1.1 christos } 70 1.1 christos /** new data el */ 71 1.1.1.2 christos static testdata_type* newdata(int val) { 72 1.1.1.2 christos testdata_type* d = (testdata_type*)calloc(1, 73 1.1.1.2 christos sizeof(testdata_type)); 74 1.1 christos if(!d) fatal_exit("out of memory"); 75 1.1 christos d->data = val; 76 1.1 christos return d; 77 1.1 christos } 78 1.1 christos 79 1.1 christos /** test bin_find_entry function and bin_overflow_remove */ 80 1.1 christos static void 81 1.1 christos test_bin_find_entry(struct lruhash* table) 82 1.1 christos { 83 1.1.1.2 christos testkey_type* k = newkey(12); 84 1.1.1.2 christos testdata_type* d = newdata(128); 85 1.1.1.2 christos testkey_type* k2 = newkey(12 + 1024); 86 1.1.1.2 christos testkey_type* k3 = newkey(14); 87 1.1.1.2 christos testkey_type* k4 = newkey(12 + 1024*2); 88 1.1.1.2 christos hashvalue_type h = myhash(12); 89 1.1 christos struct lruhash_bin bin; 90 1.1 christos memset(&bin, 0, sizeof(bin)); 91 1.1 christos bin_init(&bin, 1); 92 1.1 christos 93 1.1 christos /* remove from empty list */ 94 1.1 christos bin_overflow_remove(&bin, &k->entry); 95 1.1 christos 96 1.1 christos /* find in empty list */ 97 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k, NULL) == NULL ); 98 1.1 christos 99 1.1 christos /* insert */ 100 1.1 christos lock_quick_lock(&bin.lock); 101 1.1 christos bin.overflow_list = &k->entry; 102 1.1 christos lock_quick_unlock(&bin.lock); 103 1.1 christos 104 1.1 christos /* find, hash not OK. */ 105 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, myhash(13), k, NULL) == NULL ); 106 1.1 christos 107 1.1 christos /* find, hash OK, but cmp not */ 108 1.1 christos unit_assert( k->entry.hash == k2->entry.hash ); 109 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k2, NULL) == NULL ); 110 1.1 christos 111 1.1 christos /* find, hash OK, and cmp too */ 112 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k, NULL) == &k->entry ); 113 1.1 christos 114 1.1 christos /* remove the element */ 115 1.1 christos lock_quick_lock(&bin.lock); 116 1.1 christos bin_overflow_remove(&bin, &k->entry); 117 1.1 christos lock_quick_unlock(&bin.lock); 118 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k, NULL) == NULL ); 119 1.1 christos 120 1.1 christos /* prepend two different elements; so the list is long */ 121 1.1 christos /* one has the same hash, but different cmp */ 122 1.1 christos lock_quick_lock(&bin.lock); 123 1.1 christos unit_assert( k->entry.hash == k4->entry.hash ); 124 1.1 christos k4->entry.overflow_next = &k->entry; 125 1.1 christos k3->entry.overflow_next = &k4->entry; 126 1.1 christos bin.overflow_list = &k3->entry; 127 1.1 christos lock_quick_unlock(&bin.lock); 128 1.1 christos 129 1.1 christos /* find, hash not OK. */ 130 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, myhash(13), k, NULL) == NULL ); 131 1.1 christos 132 1.1 christos /* find, hash OK, but cmp not */ 133 1.1 christos unit_assert( k->entry.hash == k2->entry.hash ); 134 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k2, NULL) == NULL ); 135 1.1 christos 136 1.1 christos /* find, hash OK, and cmp too */ 137 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k, NULL) == &k->entry ); 138 1.1 christos 139 1.1 christos /* remove middle element */ 140 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4, NULL) 141 1.1 christos == &k4->entry ); 142 1.1 christos lock_quick_lock(&bin.lock); 143 1.1 christos bin_overflow_remove(&bin, &k4->entry); 144 1.1 christos lock_quick_unlock(&bin.lock); 145 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4, NULL) == NULL); 146 1.1 christos 147 1.1 christos /* remove last element */ 148 1.1 christos lock_quick_lock(&bin.lock); 149 1.1 christos bin_overflow_remove(&bin, &k->entry); 150 1.1 christos lock_quick_unlock(&bin.lock); 151 1.1.1.3 christos unit_assert( bin_find_entry(table, &bin, h, k, NULL) == NULL ); 152 1.1 christos 153 1.1 christos lock_quick_destroy(&bin.lock); 154 1.1 christos delkey(k); 155 1.1 christos delkey(k2); 156 1.1 christos delkey(k3); 157 1.1 christos delkey(k4); 158 1.1 christos deldata(d); 159 1.1 christos } 160 1.1 christos 161 1.1 christos /** test lru_front lru_remove */ 162 1.1 christos static void test_lru(struct lruhash* table) 163 1.1 christos { 164 1.1.1.2 christos testkey_type* k = newkey(12); 165 1.1.1.2 christos testkey_type* k2 = newkey(14); 166 1.1 christos lock_quick_lock(&table->lock); 167 1.1 christos 168 1.1 christos unit_assert( table->lru_start == NULL && table->lru_end == NULL); 169 1.1 christos lru_remove(table, &k->entry); 170 1.1 christos unit_assert( table->lru_start == NULL && table->lru_end == NULL); 171 1.1 christos 172 1.1 christos /* add one */ 173 1.1 christos lru_front(table, &k->entry); 174 1.1 christos unit_assert( table->lru_start == &k->entry && 175 1.1 christos table->lru_end == &k->entry); 176 1.1 christos /* remove it */ 177 1.1 christos lru_remove(table, &k->entry); 178 1.1 christos unit_assert( table->lru_start == NULL && table->lru_end == NULL); 179 1.1 christos 180 1.1 christos /* add two */ 181 1.1 christos lru_front(table, &k->entry); 182 1.1 christos unit_assert( table->lru_start == &k->entry && 183 1.1 christos table->lru_end == &k->entry); 184 1.1 christos lru_front(table, &k2->entry); 185 1.1 christos unit_assert( table->lru_start == &k2->entry && 186 1.1 christos table->lru_end == &k->entry); 187 1.1 christos /* remove first in list */ 188 1.1 christos lru_remove(table, &k2->entry); 189 1.1 christos unit_assert( table->lru_start == &k->entry && 190 1.1 christos table->lru_end == &k->entry); 191 1.1 christos lru_front(table, &k2->entry); 192 1.1 christos unit_assert( table->lru_start == &k2->entry && 193 1.1 christos table->lru_end == &k->entry); 194 1.1 christos /* remove last in list */ 195 1.1 christos lru_remove(table, &k->entry); 196 1.1 christos unit_assert( table->lru_start == &k2->entry && 197 1.1 christos table->lru_end == &k2->entry); 198 1.1 christos 199 1.1 christos /* empty the list */ 200 1.1 christos lru_remove(table, &k2->entry); 201 1.1 christos unit_assert( table->lru_start == NULL && table->lru_end == NULL); 202 1.1 christos lock_quick_unlock(&table->lock); 203 1.1 christos delkey(k); 204 1.1 christos delkey(k2); 205 1.1 christos } 206 1.1 christos 207 1.1 christos /** test hashtable using short sequence */ 208 1.1 christos static void 209 1.1 christos test_short_table(struct lruhash* table) 210 1.1 christos { 211 1.1.1.2 christos testkey_type* k = newkey(12); 212 1.1.1.2 christos testkey_type* k2 = newkey(14); 213 1.1.1.2 christos testdata_type* d = newdata(128); 214 1.1.1.2 christos testdata_type* d2 = newdata(129); 215 1.1 christos 216 1.1 christos k->entry.data = d; 217 1.1 christos k2->entry.data = d2; 218 1.1 christos 219 1.1 christos lruhash_insert(table, myhash(12), &k->entry, d, NULL); 220 1.1 christos lruhash_insert(table, myhash(14), &k2->entry, d2, NULL); 221 1.1 christos 222 1.1 christos unit_assert( lruhash_lookup(table, myhash(12), k, 0) == &k->entry); 223 1.1 christos lock_rw_unlock( &k->entry.lock ); 224 1.1 christos unit_assert( lruhash_lookup(table, myhash(14), k2, 0) == &k2->entry); 225 1.1 christos lock_rw_unlock( &k2->entry.lock ); 226 1.1 christos lruhash_remove(table, myhash(12), k); 227 1.1 christos lruhash_remove(table, myhash(14), k2); 228 1.1 christos } 229 1.1 christos 230 1.1 christos /** number of hash test max */ 231 1.1 christos #define HASHTESTMAX 25 232 1.1 christos 233 1.1 christos /** test adding a random element */ 234 1.1 christos static void 235 1.1.1.2 christos testadd(struct lruhash* table, testdata_type* ref[]) 236 1.1 christos { 237 1.1 christos int numtoadd = random() % HASHTESTMAX; 238 1.1.1.2 christos testdata_type* data = newdata(numtoadd); 239 1.1.1.2 christos testkey_type* key = newkey(numtoadd); 240 1.1 christos key->entry.data = data; 241 1.1 christos lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL); 242 1.1 christos ref[numtoadd] = data; 243 1.1 christos } 244 1.1 christos 245 1.1 christos /** test adding a random element */ 246 1.1 christos static void 247 1.1.1.2 christos testremove(struct lruhash* table, testdata_type* ref[]) 248 1.1 christos { 249 1.1 christos int num = random() % HASHTESTMAX; 250 1.1.1.2 christos testkey_type* key = newkey(num); 251 1.1 christos lruhash_remove(table, myhash(num), key); 252 1.1 christos ref[num] = NULL; 253 1.1 christos delkey(key); 254 1.1 christos } 255 1.1 christos 256 1.1 christos /** test adding a random element */ 257 1.1 christos static void 258 1.1.1.2 christos testlookup(struct lruhash* table, testdata_type* ref[]) 259 1.1 christos { 260 1.1 christos int num = random() % HASHTESTMAX; 261 1.1.1.2 christos testkey_type* key = newkey(num); 262 1.1 christos struct lruhash_entry* en = lruhash_lookup(table, myhash(num), key, 0); 263 1.1.1.2 christos testdata_type* data = en? (testdata_type*)en->data : NULL; 264 1.1 christos if(en) { 265 1.1 christos unit_assert(en->key); 266 1.1 christos unit_assert(en->data); 267 1.1 christos } 268 1.1 christos if(0) log_info("lookup %d got %d, expect %d", num, en? data->data :-1, 269 1.1 christos ref[num]? ref[num]->data : -1); 270 1.1 christos unit_assert( data == ref[num] ); 271 1.1 christos if(en) { lock_rw_unlock(&en->lock); } 272 1.1 christos delkey(key); 273 1.1 christos } 274 1.1 christos 275 1.1 christos /** check integrity of hash table */ 276 1.1 christos static void 277 1.1 christos check_table(struct lruhash* table) 278 1.1 christos { 279 1.1 christos struct lruhash_entry* p; 280 1.1 christos size_t c = 0; 281 1.1 christos lock_quick_lock(&table->lock); 282 1.1 christos unit_assert( table->num <= table->size); 283 1.1 christos unit_assert( table->size_mask == (int)table->size-1 ); 284 1.1 christos unit_assert( (table->lru_start && table->lru_end) || 285 1.1 christos (!table->lru_start && !table->lru_end) ); 286 1.1 christos unit_assert( table->space_used <= table->space_max ); 287 1.1 christos /* check lru list integrity */ 288 1.1 christos if(table->lru_start) 289 1.1 christos unit_assert(table->lru_start->lru_prev == NULL); 290 1.1 christos if(table->lru_end) 291 1.1 christos unit_assert(table->lru_end->lru_next == NULL); 292 1.1 christos p = table->lru_start; 293 1.1 christos while(p) { 294 1.1 christos if(p->lru_prev) { 295 1.1 christos unit_assert(p->lru_prev->lru_next == p); 296 1.1 christos } 297 1.1 christos if(p->lru_next) { 298 1.1 christos unit_assert(p->lru_next->lru_prev == p); 299 1.1 christos } 300 1.1 christos c++; 301 1.1 christos p = p->lru_next; 302 1.1 christos } 303 1.1 christos unit_assert(c == table->num); 304 1.1 christos 305 1.1 christos /* this assertion is specific to the unit test */ 306 1.1 christos unit_assert( table->space_used == 307 1.1 christos table->num * test_slabhash_sizefunc(NULL, NULL) ); 308 1.1 christos lock_quick_unlock(&table->lock); 309 1.1 christos } 310 1.1 christos 311 1.1 christos /** test adding a random element (unlimited range) */ 312 1.1 christos static void 313 1.1.1.2 christos testadd_unlim(struct lruhash* table, testdata_type** ref) 314 1.1 christos { 315 1.1 christos int numtoadd = random() % (HASHTESTMAX * 10); 316 1.1.1.2 christos testdata_type* data = newdata(numtoadd); 317 1.1.1.2 christos testkey_type* key = newkey(numtoadd); 318 1.1 christos key->entry.data = data; 319 1.1 christos lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL); 320 1.1 christos if(ref) 321 1.1 christos ref[numtoadd] = data; 322 1.1 christos } 323 1.1 christos 324 1.1 christos /** test adding a random element (unlimited range) */ 325 1.1 christos static void 326 1.1.1.2 christos testremove_unlim(struct lruhash* table, testdata_type** ref) 327 1.1 christos { 328 1.1 christos int num = random() % (HASHTESTMAX*10); 329 1.1.1.2 christos testkey_type* key = newkey(num); 330 1.1 christos lruhash_remove(table, myhash(num), key); 331 1.1 christos if(ref) 332 1.1 christos ref[num] = NULL; 333 1.1 christos delkey(key); 334 1.1 christos } 335 1.1 christos 336 1.1 christos /** test adding a random element (unlimited range) */ 337 1.1 christos static void 338 1.1.1.2 christos testlookup_unlim(struct lruhash* table, testdata_type** ref) 339 1.1 christos { 340 1.1 christos int num = random() % (HASHTESTMAX*10); 341 1.1.1.2 christos testkey_type* key = newkey(num); 342 1.1 christos struct lruhash_entry* en = lruhash_lookup(table, myhash(num), key, 0); 343 1.1.1.2 christos testdata_type* data = en? (testdata_type*)en->data : NULL; 344 1.1 christos if(en) { 345 1.1 christos unit_assert(en->key); 346 1.1 christos unit_assert(en->data); 347 1.1 christos } 348 1.1 christos if(0 && ref) log_info("lookup unlim %d got %d, expect %d", num, en ? 349 1.1 christos data->data :-1, ref[num] ? ref[num]->data : -1); 350 1.1 christos if(data && ref) { 351 1.1 christos /* its okay for !data, it fell off the lru */ 352 1.1 christos unit_assert( data == ref[num] ); 353 1.1 christos } 354 1.1 christos if(en) { lock_rw_unlock(&en->lock); } 355 1.1 christos delkey(key); 356 1.1 christos } 357 1.1 christos 358 1.1 christos /** test with long sequence of adds, removes and updates, and lookups */ 359 1.1 christos static void 360 1.1 christos test_long_table(struct lruhash* table) 361 1.1 christos { 362 1.1 christos /* assuming it all fits in the hashtable, this check will work */ 363 1.1.1.2 christos testdata_type* ref[HASHTESTMAX * 100]; 364 1.1 christos size_t i; 365 1.1 christos memset(ref, 0, sizeof(ref)); 366 1.1 christos /* test assumption */ 367 1.1 christos if(0) log_info(" size %d x %d < %d", (int)test_slabhash_sizefunc(NULL, NULL), 368 1.1 christos (int)HASHTESTMAX, (int)table->space_max); 369 1.1 christos unit_assert( test_slabhash_sizefunc(NULL, NULL)*HASHTESTMAX < table->space_max); 370 1.1 christos if(0) lruhash_status(table, "unit test", 1); 371 1.1 christos srandom(48); 372 1.1 christos for(i=0; i<1000; i++) { 373 1.1 christos /* what to do? */ 374 1.1 christos if(i == 500) { 375 1.1 christos lruhash_clear(table); 376 1.1 christos memset(ref, 0, sizeof(ref)); 377 1.1 christos continue; 378 1.1 christos } 379 1.1 christos switch(random() % 4) { 380 1.1 christos case 0: 381 1.1 christos case 3: 382 1.1 christos testadd(table, ref); 383 1.1 christos break; 384 1.1 christos case 1: 385 1.1 christos testremove(table, ref); 386 1.1 christos break; 387 1.1 christos case 2: 388 1.1 christos testlookup(table, ref); 389 1.1 christos break; 390 1.1 christos default: 391 1.1 christos unit_assert(0); 392 1.1 christos } 393 1.1 christos if(0) lruhash_status(table, "unit test", 1); 394 1.1 christos check_table(table); 395 1.1 christos unit_assert( table->num <= HASHTESTMAX ); 396 1.1 christos } 397 1.1 christos 398 1.1 christos /* test more, but 'ref' assumption does not hold anymore */ 399 1.1 christos for(i=0; i<1000; i++) { 400 1.1 christos /* what to do? */ 401 1.1 christos switch(random() % 4) { 402 1.1 christos case 0: 403 1.1 christos case 3: 404 1.1 christos testadd_unlim(table, ref); 405 1.1 christos break; 406 1.1 christos case 1: 407 1.1 christos testremove_unlim(table, ref); 408 1.1 christos break; 409 1.1 christos case 2: 410 1.1 christos testlookup_unlim(table, ref); 411 1.1 christos break; 412 1.1 christos default: 413 1.1 christos unit_assert(0); 414 1.1 christos } 415 1.1 christos if(0) lruhash_status(table, "unlim", 1); 416 1.1 christos check_table(table); 417 1.1 christos } 418 1.1 christos } 419 1.1 christos 420 1.1 christos /** structure to threaded test the lru hash table */ 421 1.1 christos struct test_thr { 422 1.1 christos /** thread num, first entry. */ 423 1.1 christos int num; 424 1.1 christos /** id */ 425 1.1.1.2 christos ub_thread_type id; 426 1.1 christos /** hash table */ 427 1.1 christos struct lruhash* table; 428 1.1 christos }; 429 1.1 christos 430 1.1 christos /** main routine for threaded hash table test */ 431 1.1 christos static void* 432 1.1 christos test_thr_main(void* arg) 433 1.1 christos { 434 1.1 christos struct test_thr* t = (struct test_thr*)arg; 435 1.1 christos int i; 436 1.1 christos log_thread_set(&t->num); 437 1.1 christos for(i=0; i<1000; i++) { 438 1.1 christos switch(random() % 4) { 439 1.1 christos case 0: 440 1.1 christos case 3: 441 1.1 christos testadd_unlim(t->table, NULL); 442 1.1 christos break; 443 1.1 christos case 1: 444 1.1 christos testremove_unlim(t->table, NULL); 445 1.1 christos break; 446 1.1 christos case 2: 447 1.1 christos testlookup_unlim(t->table, NULL); 448 1.1 christos break; 449 1.1 christos default: 450 1.1 christos unit_assert(0); 451 1.1 christos } 452 1.1 christos if(0) lruhash_status(t->table, "hashtest", 1); 453 1.1 christos if(i % 100 == 0) /* because of locking, not all the time */ 454 1.1 christos check_table(t->table); 455 1.1 christos } 456 1.1 christos check_table(t->table); 457 1.1 christos return NULL; 458 1.1 christos } 459 1.1 christos 460 1.1 christos /** test hash table access by multiple threads */ 461 1.1 christos static void 462 1.1 christos test_threaded_table(struct lruhash* table) 463 1.1 christos { 464 1.1 christos int numth = 10; 465 1.1 christos struct test_thr t[100]; 466 1.1 christos int i; 467 1.1 christos 468 1.1 christos for(i=1; i<numth; i++) { 469 1.1 christos t[i].num = i; 470 1.1 christos t[i].table = table; 471 1.1 christos ub_thread_create(&t[i].id, test_thr_main, &t[i]); 472 1.1 christos } 473 1.1 christos 474 1.1 christos for(i=1; i<numth; i++) { 475 1.1 christos ub_thread_join(t[i].id); 476 1.1 christos } 477 1.1 christos if(0) lruhash_status(table, "hashtest", 1); 478 1.1 christos } 479 1.1 christos 480 1.1 christos void lruhash_test(void) 481 1.1 christos { 482 1.1 christos /* start very very small array, so it can do lots of table_grow() */ 483 1.1 christos /* also small in size so that reclaim has to be done quickly. */ 484 1.1 christos struct lruhash* table ; 485 1.1 christos unit_show_feature("lruhash"); 486 1.1 christos table = lruhash_create(2, 8192, 487 1.1 christos test_slabhash_sizefunc, test_slabhash_compfunc, 488 1.1 christos test_slabhash_delkey, test_slabhash_deldata, NULL); 489 1.1 christos test_bin_find_entry(table); 490 1.1 christos test_lru(table); 491 1.1 christos test_short_table(table); 492 1.1 christos test_long_table(table); 493 1.1 christos lruhash_delete(table); 494 1.1 christos table = lruhash_create(2, 8192, 495 1.1 christos test_slabhash_sizefunc, test_slabhash_compfunc, 496 1.1 christos test_slabhash_delkey, test_slabhash_deldata, NULL); 497 1.1 christos test_threaded_table(table); 498 1.1 christos lruhash_delete(table); 499 1.1 christos } 500