/*
* Copyright (c) 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_IDSTR(id, "@(#)$Id: t-adbr-0.c,v 1.10 2006/10/21 05:02:41 ca Exp $")
#include "sm/debug.h"
#include "sm/heap.h"
#include "sm/sysexits.h"
#include "sm/test.h"
#include "sm/io.h"
#include "sm/rfc2821.h"
#include "sm/actdb-int.h"
#define QMGR_DEBUG_DEFINE 1
#include "sm/qmgrdbg.h"
static int Verbose = 0;
#if SM_HEAP_CHECK
# include "sm/io.h"
extern SM_DEBUG_T SmHeapCheck;
# define HEAP_CHECK (SmHeapCheck > 0)
#else
# define HEAP_CHECK 0
#endif
#define SM_AQ_RCPTS 256
#define RCPT_MAX_LEN 256
#define SMT_NOCHECKS 0x01
#define SMT_APPEND 0x02
static sm_ret_T
aqr_test1(aq_rcpt_P aq_rcpt, int n)
{
int direction, i;
aq_rcpt_P aq_rcpt_nxt, aq_rcpt_prev, aq_rcpt_f;
if (Verbose > 0)
sm_io_fprintf(smioerr, "\naq_rcpt=%p, domain=%S\n",
aq_rcpt, aq_rcpt->aqr_domain);
#define DIR(d) ((d > 0) ? 1 : ((d < 0) ? (-1) : 0))
if (Verbose > 0)
sm_io_fprintf(smioerr, "LIST: 0: aq_rcpt=%p, domain=%S\n",
aq_rcpt, aq_rcpt->aqr_domain);
for (aq_rcpt_prev = aq_rcpt, aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt), i = 1;
aq_rcpt_nxt != aq_rcpt;
aq_rcpt_prev = aq_rcpt_nxt, aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt_nxt),
i++)
{
direction = sm_str_casecmp(aq_rcpt_prev->aqr_domain,
aq_rcpt_nxt->aqr_domain);
direction = DIR(direction);
if (Verbose > 0)
sm_io_fprintf(smioerr,
"LIST: %2d: aq_rcpt=%p, domain=%S, dir=%d\n",
i, aq_rcpt_nxt, aq_rcpt_nxt->aqr_domain,
direction);
}
aq_rcpt_f = NULL;
for (aq_rcpt_prev = aq_rcpt, aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt), i = 0;
aq_rcpt_nxt != aq_rcpt;
aq_rcpt_prev = aq_rcpt_nxt, aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt_nxt),
i++)
{
direction = sm_str_casecmp(aq_rcpt_prev->aqr_domain,
aq_rcpt_nxt->aqr_domain);
direction = DIR(direction);
if (Verbose > 0)
sm_io_fprintf(smioerr,
"%2d/0: aq_rcpt=%p, domain=%S, dir=%d\n",
i, aq_rcpt_prev, aq_rcpt_prev->aqr_domain,
direction);
if (direction > 0)
{
if (Verbose > 0)
sm_io_fprintf(smioerr,
"BREAK: %p, %S, nxt=%p, %S, dir=%d\n",
aq_rcpt_prev, aq_rcpt_prev->aqr_domain,
aq_rcpt_nxt, aq_rcpt_nxt->aqr_domain,
direction);
aq_rcpt_f = aq_rcpt_nxt;
break;
}
}
if (aq_rcpt_f != NULL)
{
for (aq_rcpt_prev = aq_rcpt_f,
aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt_f), i = 0;
aq_rcpt_nxt != aq_rcpt_f;
aq_rcpt_prev = aq_rcpt_nxt,
aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt_nxt), i++)
{
direction = sm_str_casecmp(aq_rcpt_prev->aqr_domain,
aq_rcpt_nxt->aqr_domain);
direction = DIR(direction);
if (Verbose > 0)
sm_io_fprintf(smioerr,
"%2d: aq_rcpt=%p, domain=%S, dir=%d\n",
i, aq_rcpt_prev, aq_rcpt_prev->aqr_domain,
direction);
SM_TEST(direction <= 0);
if (direction > 0 && Verbose > 0)
sm_io_fprintf(smioerr,
"ERROR: %p, %S, nxt=%p, %S, dir=%d\n",
aq_rcpt_prev, aq_rcpt_prev->aqr_domain,
aq_rcpt_nxt, aq_rcpt_nxt->aqr_domain,
direction);
}
}
SM_TEST(i == n);
if (i != n && Verbose > 0)
sm_io_fprintf(smioerr, "i=%2d, n=%2d\n", i, n);
if (Verbose > 0)
sm_io_fprintf(smioerr, "%2d: aq_rcpt=%p, domain=%S [LAST]\n",
i, aq_rcpt_nxt, aq_rcpt_nxt->aqr_domain);
sm_io_flush(smioerr);
return SM_SUCCESS;
}
static sm_ret_T
aqr_tests(aq_rcpt_P aq_rcpt)
{
int direction;
aq_rcpt_P aq_rcpt_nxt, aq_rcpt_prev, aq_rcpt_f, aq_rcpt_l;
aq_rcpt_f = aq_rcpt_l = aq_rcpt;
if (Verbose > 0)
sm_io_fprintf(smioout, "\naq_rcpt=%p, domain=%S\n",
aq_rcpt, aq_rcpt->aqr_domain);
for (aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt);
aq_rcpt_nxt != aq_rcpt;
aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt_nxt))
{
direction = sm_str_casecmp(aq_rcpt_nxt->aqr_domain,
aq_rcpt_f->aqr_domain);
if (direction < 0)
aq_rcpt_f = aq_rcpt_nxt;
direction = sm_str_casecmp(aq_rcpt_nxt->aqr_domain,
aq_rcpt_l->aqr_domain);
if (direction > 0)
aq_rcpt_l = aq_rcpt_nxt;
}
for (aq_rcpt_nxt = aq_rcpt_f, aq_rcpt_prev = aq_rcpt_f;
aq_rcpt_nxt != aq_rcpt_l;
aq_rcpt_nxt = AQR_SS_SUCC(aq_rcpt_nxt))
{
if (Verbose > 0)
sm_io_fprintf(smioout, "aq_rcpt=%p, domain=%S\n",
aq_rcpt_nxt, aq_rcpt_nxt->aqr_domain);
direction = sm_str_casecmp(aq_rcpt_prev->aqr_domain,
aq_rcpt_nxt->aqr_domain);
SM_TEST(direction <= 0);
aq_rcpt_prev = aq_rcpt_nxt;
}
if (Verbose > 0)
sm_io_fprintf(smioout, "aq_rcpt=%p, domain=%S\n",
aq_rcpt_nxt, aq_rcpt_nxt->aqr_domain);
sm_io_flush(smioout);
return SM_SUCCESS;
}
static sm_ret_T
aqr_test0(uint lim, uint flags)
{
sm_ret_T ret;
int i, r;
sm_str_P str;
char buf[RCPT_MAX_LEN];
aq_rcpt_P aq_rcpt, aq_rcpt_prev;
aq_rcpt_prev = NULL;
ret = SM_SUCCESS;
srand(time(0));
for (i = 0; i < lim; i++)
{
ret = aq_rcpt_new(&aq_rcpt);
SM_TEST_ERR(ret);
sm_snprintf(aq_rcpt->aqr_ss_ta_id,
sizeof(aq_rcpt->aqr_ss_ta_id), SMTPS_STID_FORMAT,
(ulonglong_T) i, i);
#if 1
r = rand();
if (Verbose > 1)
sm_io_fprintf(smioout, "i=%d, r=%8d\n", i, r);
#else /* 0 */
switch (i)
{
case 0: r = 1074254950; break;
case 1: r = 1391506343; break;
case 2: r = 23302228; break;
case 3: r = 1649818621; break;
default: break;
}
#endif /* 0 */
sm_snprintf(buf, sizeof(buf), "<a-%d@%d-domain.tld>", i, r);
str = sm_str_scpy0(NULL, buf, sizeof(buf));
if (aq_rcpt->aqr_pa != NULL)
sm_str_free(aq_rcpt->aqr_pa);
aq_rcpt->aqr_pa = str;
str = NULL;
/* get domain part */
ret = aq_rcpt_set_domain(aq_rcpt, NULL);
if (sm_is_err(ret))
goto error;
AQR_DA_INIT(aq_rcpt);
if (SM_IS_FLAG(flags, SMT_APPEND))
{
if (aq_rcpt_prev == NULL)
AQR_SS_INIT(aq_rcpt);
else
AQR_SS_APP(aq_rcpt_prev, aq_rcpt);
}
else
{
ret = aq_rcpt_ss_insert(aq_rcpt_prev, aq_rcpt);
if (sm_is_err(ret))
goto error;
}
aq_rcpt_prev = aq_rcpt;
if (!SM_IS_FLAG(flags, SMT_NOCHECKS))
{
ret = aqr_tests(aq_rcpt);
ret = aqr_test1(aq_rcpt, i);
}
}
if (!SM_IS_FLAG(flags, SMT_NOCHECKS))
{
ret = aqr_tests(aq_rcpt);
ret = aqr_test1(aq_rcpt, i - 1);
}
return ret;
error:
return ret;
}
static void
usage(const char *prg)
{
sm_io_fprintf(smioerr, "usage: %s [options]\n", prg);
sm_io_fprintf(smioerr, "Test AQ recipient sorting (domains are random numbers)\n");
sm_io_fprintf(smioerr, "options:\n");
sm_io_fprintf(smioerr, "-a append only, don't sort\n");
sm_io_fprintf(smioerr, "-n n specify number of recipients to sort\n");
sm_io_fprintf(smioerr, "-t don't perform tests, just sort\n");
sm_io_fprintf(smioerr, "-V increase verbosity\n");
exit(EX_USAGE);
}
int
main(int argc, char **argv)
{
int c;
uint n, flags;
sm_ret_T r;
char *prg;
prg = argv[0];
n = SM_AQ_RCPTS;
flags = 0;
#if SM_HEAP_CHECK
SmHeapCheck = 0;
#endif
while ((c = getopt(argc, argv, "aH:n:tV")) != -1)
{
switch (c)
{
case 'a':
flags |= SMT_NOCHECKS|SMT_APPEND;
break;
case 'n':
n = (uint) strtoul(optarg, NULL, 0);
break;
#if SM_HEAP_CHECK
case 'H':
SmHeapCheck = atoi(optarg);
break;
#endif
case 't':
flags |= SMT_NOCHECKS;
break;
case 'V':
++Verbose;
break;
default:
usage(prg);
return EX_USAGE;
}
}
sm_test_begin(argc, argv, "test adbr 0");
r = aqr_test0(n, flags);
#if SM_HEAP_CHECK
if (HEAP_CHECK)
{
sm_io_fprintf(smioout, "heap should be empty except for makebuf:\n");
sm_heap_report(smioout, 3);
}
#endif
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1