/* * 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(); }