/*
* 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-rsct-0.c,v 1.15 2005/09/29 17:17:49 ca Exp $")
#include <stdio.h>
#include "sm/memops.h"
#include "sm/assert.h"
#include "sm/rpool.h"
#include "sm/rsct.h"
#include "sm/test.h"
#define CSIZE 13
#define HTSIZE 25
#define CHARS 64
#define NH 61 /* must be less than CHARS */
#define HLEN 12
#define KLEN (HLEN - 2)
#define TYPES (2u)
int Verbose = 0;
char hashes[NH][HLEN];
typedef struct cdctx_S cdctx_T, *cdctx_P;
struct cdctx_S
{
sm_rpool_P ctx_rpool;
};
static bool
chktype(const char *str, uint type)
{
uint i;
for (i = 0; i < NH; i++)
{
if (strcmp(str, hashes[i]) == 0)
return (type == (i % TYPES));
}
return false;
}
static void *
create(const char *key, uint len, void *value, void *ctx, uint type)
{
char *n;
cdctx_P cdctx;
sm_rpool_P rpool;
cdctx = (cdctx_P) ctx;
rpool = cdctx->ctx_rpool;
n = sm_rpool_strdup(rpool, value);
SM_TEST(chktype(key, type));
if (Verbose > 1)
fprintf(stderr, "create(%s, %u)=%s\n", key, type, n == NULL ? "<NULL>" : n);
return n;
}
static sm_ret_T
delete(void *data, void *ctx, uint type)
{
cdctx_P cdctx;
sm_rpool_P rpool;
cdctx = (cdctx_P) ctx;
rpool = cdctx->ctx_rpool;
SM_TEST(chktype((char *) data, type));
if (Verbose > 1)
fprintf(stderr, "delete(%s, %u)\n", (char *)data, type);
sm_rpool_free(rpool, data);
return SM_SUCCESS;
}
static int cnt = 0;
static void
action(const char *key, const void *value, void *ctx, void *walk_ctx, uint type)
{
if (Verbose > 1)
fprintf(stderr, "action(%s, %d)=%s\n", key, type, (char *) value);
++cnt;
}
static void
testh(uint csize, uint htsize)
{
int i, j, k;
rsct_P ct;
void *ctx;
char *res;
sm_ret_T ret;
#if SM_BHTABLE_PERF
char buf[1024];
#endif
cdctx_T cdctx;
cdctx.ctx_rpool = NULL;
ctx = (void *) &cdctx;
ct = rsct_new(csize, htsize, create, delete, ctx);
SM_TEST(ct != NULL);
if (ct == NULL)
return;
for (i = 0; i < NH; i++)
{
for (j = 0; j < HLEN; j++)
{
hashes[i][j] = 'A' + ((i + j) % CHARS);
}
hashes[i][HLEN - 1] = '\0';
}
/* add CSIZE entries to RSC */
for (j = 0; j < CSIZE; j++)
{
i = j % NH;
ret = rsct_add(ct, false, i % TYPES, hashes[i], KLEN, hashes[i],
(void **)&res, THR_LOCK_UNLOCK);
SM_TEST(!sm_is_err(ret));
SM_TEST(strcmp(res, hashes[i]) == 0);
cnt = 0;
rsct_walk(ct, action, (void *) 0, THR_LOCK_UNLOCK);
SM_TEST(cnt == j + 1);
k = rsct_usage(ct);
SM_TEST(k == (int) ((j + 1) * 100 / CSIZE));
}
/* make sure the rest isn't in the RSC */
for (k = CSIZE; k < NH; k++)
{
res = (char *) rsct_lookup(ct, hashes[k], KLEN,
THR_LOCK_UNLOCK);
SM_TEST(res == NULL);
if (Verbose > 0 && res != NULL)
fprintf(stderr, "j=%d, k=%d, res=%s\n",
j, k, res);
k = rsct_usage(ct);
SM_TEST(k == 100);
}
/* check entries in RSC */
for (j = 0; j < CSIZE; j++)
{
i = j % NH;
res = (char *) rsct_lookup(ct, hashes[i], KLEN,
THR_LOCK_UNLOCK);
SM_TEST(strcmp(res, hashes[i]) == 0);
}
for (j = 0; j < CSIZE * 3; j++)
{
i = j % NH;
ret = rsct_add(ct, true, i % TYPES, hashes[i], KLEN, hashes[i],
(void **)&res, THR_LOCK_UNLOCK);
SM_TEST(!sm_is_err(ret));
SM_TEST(strcmp(res, hashes[i]) == 0);
cnt = 0;
rsct_walk(ct, action, (void *) 0, THR_LOCK_UNLOCK);
SM_TEST(cnt == CSIZE);
/* make sure that the other entries are not in the cache */
if (j > CSIZE)
{
for (k = j + 1; k < NH; k++)
{
res = (char *) rsct_lookup(ct, hashes[k], KLEN,
THR_LOCK_UNLOCK);
SM_TEST(res == NULL);
if (Verbose > 0 && res != NULL)
fprintf(stderr, "j=%d, k=%d, res=%s\n",
j, k, res);
}
}
k = rsct_usage(ct);
SM_TEST(k == 100);
}
/* XXX need a better test that shows the MRU feature */
#if SM_BHTABLE_PERF
if (Verbose > 0)
{
rsct_stats(ct, buf, sizeof(buf));
printf("%s", buf);
}
#endif /* SM_BHTABLE_PERF */
rsct_free(ct);
}
int
main(int argc, char *argv[])
{
int c;
uint csize, htsize;
csize = CSIZE;
htsize = HTSIZE;
while ((c = getopt(argc, argv, "c:h:V")) != -1)
{
switch (c)
{
case 'c':
csize = (uint) atoi(optarg);
break;
case 'h':
htsize = (uint) atoi(optarg);
break;
case 'V':
++Verbose;
break;
default:
return(1);
}
}
sm_test_begin(argc, argv, "test rsct 0");
testh(csize, htsize);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1