/*
 * 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-1.c,v 1.8 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

static char *list[] = {
	"<_@Sendmail.ORG>",
	"<_@sendmailx.org>",
	"<_@sendmail.com>",
	"<_@Sendmail.ORG>",
	"<_@sendmail.com>",
	"<_@Sendmail.COM>",
	"<_@Sendmail.COM>",
	"<_@sendmail.com>",
	"<_@sendmail.com>",
	"<_@sendmail.com>",
	"<_@sendmail.com>",
	"<_@sendmail.com>",
	"<_@sendmail.com>",
	"<_@sendmail.org>",
	"<_@csuchico.edu>",
	"<_@niu.edu>",
	"<_@uni-kiel.de>",
	"<_@informatik.uni-kiel.de>",
	"<_@vt.edu>",
	"<_@andrew.cmu.edu>",
	"<_@onet.pl>",
	"<_@Sendmail.ORG>",
	"<_@debian.org>",
	"<_@nmt.edu>",
	"<_@uwaterloo.ca>",
	"<_@yale.edu>",
	"<_@uni-erlangen.de>",
	"<_@yahoo.com>",
	"<_@earthlink.net>",
	"<_@hotmail.com>",
	"<_@hp.com>",
	"<_@polytechnique.fr>",
	"<_@gmail.com>",
	NULL
	};


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_test0(void)
{
	sm_ret_T ret;
	int i;
	sm_str_P str;
	aq_rcpt_P aq_rcpt_a[SM_AQ_RCPTS];
	aq_rcpt_P aq_rcpt, aq_rcpt_prev;

	aq_rcpt_prev = NULL;
	srand(time(0));
	for (i = 0; i < SM_AQ_RCPTS; i++)
	{
		if (list[i] == NULL)
			break;

		ret = aq_rcpt_new(&(aq_rcpt_a[i]));
		SM_TEST_ERR(ret);
		aq_rcpt = aq_rcpt_a[i];

		sm_snprintf(aq_rcpt->aqr_ss_ta_id,
			sizeof(aq_rcpt->aqr_ss_ta_id), SMTPS_STID_FORMAT,
			(ulonglong_T) i, i);

		str = sm_str_scpy0(NULL, list[i], strlen(list[i]) + 2);
		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);
		SM_TEST_ERR(ret);

		AQR_DA_INIT(aq_rcpt);
		ret = aq_rcpt_ss_insert(aq_rcpt_prev, aq_rcpt);
		SM_TEST_ERR(ret);
		aq_rcpt_prev = aq_rcpt;
		ret = aqr_test1(aq_rcpt_a[0], i);
	}

	ret = aqr_test1(aq_rcpt_a[0], 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 hardcoded)\n");
	sm_io_fprintf(smioerr, "options:\n");
	sm_io_fprintf(smioerr, "-V    increase verbosity\n");
	exit(0);
}

int
main(int argc, char **argv)
{
	int c;
	sm_ret_T r;

#if SM_HEAP_CHECK
	SmHeapCheck = 0;
#endif
	while ((c = getopt(argc, argv, "H:V")) != -1)
	{
		switch (c)
		{
#if SM_HEAP_CHECK
		  case 'H':
			SmHeapCheck = atoi(optarg);
			break;
#endif
		  case 'V':
			++Verbose;
			break;
		  default:
			usage(argv[0]);
			return EX_USAGE;
		}
	}

	sm_test_begin(argc, argv, "test adbr 0");

	r = aqr_test0();

#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 /* SM_HEAP_CHECK */
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1