/*
* 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 <stdio.h>
#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();
}
syntax highlighted by Code2HTML, v. 0.9.1