/* * Copyright (c) 2002, 2004, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * */ #include "sm/generic.h" SM_RCSID("@(#)$Id: t-bhtable.c,v 1.20 2005/04/14 17:14:02 ca Exp $") #include #include "sm/error.h" #include "sm/heap.h" #include "sm/bhtable.h" #include "sm/memops.h" #include "sm/test.h" #include "sm/io.h" #if SM_HEAP_CHECK extern SM_DEBUG_T SmHeapCheck; # define HEAP_CHECK (SmHeapCheck > 0) #else /* SM_HEAP_CHECK */ static int SmHeapCheck; # define HEAP_CHECK false #endif /* SM_HEAP_CHECK */ #define T_BHT_SIZE 1023 #define NH 255 #define HLEN 128 #define KLEN (HLEN - 2) int Verbose = 0; char hashes[NH][HLEN]; /* ARGSUSED1 */ static sm_ret_T action(bht_entry_P info, void *ctx) { int i; (void) ctx; for (i = 0; i < NH; i++) { if (sm_memeq(info->bhe_value, hashes[i], KLEN)) return SM_SUCCESS; } SM_TEST(i < NH); return SM_FAILURE; } static void stats(bht_P tn) { #if SM_BHT_PERF char buf[1024]; if (Verbose > 0) { bht_stats(tn, buf, sizeof(buf)); printf("%s", buf); } #else /* SM_BHT_PERF */ (void) tn; #endif /* SM_BHT_PERF */ } static void testh(uint bhtsize) { int i, j; char *str; bht_P tn; bht_entry_P bi; sm_ret_T ret; tn = NULL; tn = bht_new(bhtsize, bhtsize * 2); SM_TEST(tn != NULL); if (tn == NULL) return; for (i = 0; i < NH; i++) { for (j = 0; j < HLEN; j++) { hashes[i][j] = ' ' + (i + j) % 96; } hashes[i][HLEN - 1] = '\0'; } for (i = 0; i < NH; i++) { ret = bht_add(tn, hashes[i], KLEN, hashes[i], &bi); SM_TEST(ret == SM_SUCCESS); SM_TEST(bi != NULL); } for (i = 0; i < NH; i++) { str = bht_find(tn, hashes[i], KLEN); SM_TEST(str != NULL); if (str == NULL) goto error; SM_TEST(sm_memeq(str, hashes[i], KLEN)); } bht_walk(tn, action, NULL); for (i = 0; i < NH; i++) { str = bht_find(tn, hashes[i], HLEN - 1); SM_TEST(str == NULL); } for (i = 0; i < NH; i++) { bht_rm(tn, hashes[i], KLEN, NULL, NULL); for (j = i + 1; j < NH; j++) { str = bht_find(tn, hashes[j], KLEN); SM_TEST(str != NULL); if (str == NULL) goto error; SM_TEST(sm_memeq(str, hashes[j], KLEN)); } } error: stats(tn); bht_destroy(tn, NULL, NULL); } static void testd(uint bhtsize) { int i, j; char *str; bht_P tn; bht_entry_P bi; sm_ret_T ret; tn = NULL; tn = bht_new(bhtsize, bhtsize * 2); SM_TEST(tn != NULL); if (tn == NULL) return; for (i = 0; i < NH; i++) { for (j = 0; j < HLEN; j++) { hashes[i][j] = ' ' + (i + j) % 96; } hashes[i][HLEN - 1] = '\0'; } i = 0; ret = bht_add(tn, hashes[i], KLEN, hashes[i], &bi); SM_TEST(ret == SM_SUCCESS); SM_TEST(bi != NULL); for (i = 0; i < NH; i++) { ret = bht_add(tn, hashes[i], KLEN, hashes[i], &bi); SM_TEST(ret == SM_SUCCESS); SM_TEST(bi != NULL); } i = 0; bht_rm_all(tn, hashes[i], KLEN, NULL, NULL); for (i = 1; i < NH; i++) { bht_rm(tn, hashes[i], KLEN, NULL, NULL); for (j = i + 1; j < NH; j++) { if (sm_memeq(hashes[0], hashes[j], KLEN)) continue; str = bht_find(tn, hashes[j], KLEN); SM_TEST(str != NULL); if (str == NULL) goto error; SM_TEST(sm_memeq(str, hashes[j], KLEN)); } } error: stats(tn); bht_destroy(tn, NULL, NULL); } int main(int argc, char *argv[]) { int c; uint bhtsize; bhtsize = T_BHT_SIZE; SmHeapCheck = 0; while ((c = getopt(argc, argv, "H:s:V")) != -1) { switch (c) { case 'H': SmHeapCheck = atoi(optarg); break; case 's': bhtsize = (uint) atoi(optarg); break; case 'V': ++Verbose; break; default: return(1); } } sm_test_begin(argc, argv, "test bhtable"); if (HEAP_CHECK) { sm_io_fprintf(smioout, "Heap report before testh(NULL)\n"); sm_heap_report(smioout, 3); } testh(bhtsize); if (HEAP_CHECK) { sm_io_fprintf(smioout, "Heap report after testh(NULL)\n"); sm_heap_report(smioout, 3); } testd(bhtsize); return sm_test_end(); }