/*
 * Copyright (c) 2002, 2004 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-bht2.c,v 1.12 2004/12/26 04:08:54 ca Exp $")

#include <stdio.h>

#include "sm/error.h"
#include "sm/rpool.h"
#include "sm/bht2.h"
#include "sm/memops.h"
#include "sm/test.h"

#define T_BHT_SIZE	1023
#define NH	255
#define HLEN	128
#define KLEN	(HLEN - 2)
#define KLEN2	4

int Verbose = 0;
char hashes[NH][HLEN];
char keys2[NH][KLEN2];

static sm_ret_T
action(bht2_entry_P info, void *ctx)
{
	int i;

	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(bht2_P tn)
{
#if SM_BHT_PERF
	char buf[1024];

	if (Verbose > 0)
	{
		bht2_stats(tn, buf, sizeof(buf));
		printf("%s", buf);
	}
#endif /* SM_BHT_PERF */
}

static void
testh(uint bhtsize)
{
	int i, j;
	char *str;
	bht2_P tn;
	bht2_entry_P bi;
	sm_ret_T ret;

	tn = NULL;
	tn = bht2_new(bhtsize, 0);
	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 (j = 0; j < KLEN2; j++)
		{
			keys2[i][j] = ' ' + (i + j) % 96;
		}
		keys2[i][KLEN2 - 1] = '\0';
	}

	for (i = 0; i < NH; i++)
	{
		ret = bht2_add(tn, hashes[i], KLEN,
				keys2[i], KLEN2,
				hashes[i], &bi);
		SM_TEST(ret == SM_SUCCESS);
		SM_TEST(bi != NULL);
	}

	for (i = 0; i < NH; i++)
	{
		str = bht2_find(tn, hashes[i], KLEN);
		SM_TEST(str != NULL);
		SM_TEST(sm_memeq(str, hashes[i], KLEN));
	}

	for (i = 0; i < NH; i++)
	{
		str = bht2_find_first(tn, keys2[i], KLEN2);
		SM_TEST(str != NULL);
		SM_TEST(sm_memeq(str, hashes[i], KLEN2));
	}

	for (i = 0; i < NH; i++)
	{
		j = 0;

		bi = bht2_locate_first(tn, keys2[i], KLEN2);
		SM_TEST(bi != NULL);
		SM_TEST(sm_memeq(bi->bhe_value, hashes[i], KLEN2));
		while ((bi = bht2_locate_next(tn, bi)) != NULL)
		{
			++j;
			SM_TEST(sm_memeq(bi->bhe_value, hashes[i], KLEN2));
		}
		SM_TEST(j > 0);
	}


	bht2_walk(tn, action, NULL);

	for (i = 0; i < NH; i++)
	{
		str = bht2_find(tn, hashes[i], HLEN - 1);
		SM_TEST(str == NULL);
	}
	for (i = 0; i < NH; i++)
	{
		bht2_rm(tn, hashes[i], KLEN, NULL, NULL);
		for (j = i + 1; j < NH; j++)
		{
			str = bht2_find(tn, hashes[j], KLEN);
			SM_TEST(str != NULL);
			SM_TEST(sm_memeq(str, hashes[j], KLEN));
		}
	}
	stats(tn);
	bht2_destroy(tn, NULL, NULL);
}

int
main(int argc, char *argv[])
{
	int c;
	uint bhtsize;

	bhtsize = T_BHT_SIZE;
	while ((c = getopt(argc, argv, "s:V")) != -1)
	{
		switch (c)
		{
		  case 's':
			bhtsize = (uint) atoi(optarg);
			break;
		  case 'V':
			++Verbose;
			break;
		  default:
			return(1);
		}
	}
	sm_test_begin(argc, argv, "test bhtable");
	testh(bhtsize);
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1