/* * Copyright (c) 2006 Claus Assmann * * By using this file, you agree to the terms and conditions set * forth in the license/LICENSE.3C file which can be found at the * top level of this source code distribution. */ #include "sm/generic.h" SM_IDSTR(id, "@(#)$Id: t-adbr-2.c,v 1.3 2006/10/22 02:57:51 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; static uint Lookups = 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_ctx_P aq_ctx; aq_rcpt_P aq_rcpt, aq_rcpt_prev; sessta_id_T *ta_ids; aq_ctx = NULL; aq_rcpt_prev = NULL; ta_ids = NULL; ret = SM_SUCCESS; ret = aq_open(NULL /*qmgr_ctx*/, &aq_ctx, lim * 2, AQ_OPEN_FL_NOHT); srand(time(0)); if (Lookups > 0) { ta_ids = sm_malloc(lim * sizeof(*ta_ids)); SM_TEST_E(ta_ids != NULL); } for (i = 0; i < lim; i++) { ret = aq_rcpt_add_new(aq_ctx, NULL, &aq_rcpt, 0, 0); SM_TEST_ERR(ret); SM_TEST_ERR(aq_rcpt != NULL); aq_rcpt->aqr_idx = i; sm_snprintf(aq_rcpt->aqr_ss_ta_id, sizeof(aq_rcpt->aqr_ss_ta_id), SMTPS_STID_FORMAT, (ulonglong_T) rand(), rand()); if (Lookups > 0 && ta_ids != NULL) SESSTA_COPY(ta_ids[i], aq_rcpt->aqr_ss_ta_id); #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), "", 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); } if (Lookups > 0 && ta_ids != NULL) { #if HAVE_MONCONTROL moncontrol(1); #endif for (i = 0; i < Lookups; i++) { r = rand() % lim; SM_TEST_E(r >= 0); SM_TEST_E(r < lim); SM_TEST_E(ta_ids[r] != NULL); ret = aq_rcpt_find_ss(aq_ctx, ta_ids[r], r, 0, &aq_rcpt); SM_TEST(SM_SUCCESS == ret); } #if HAVE_MONCONTROL moncontrol(0); #endif } 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 and lookups (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, "-l n lookup entries\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; #if HAVE_MONCONTROL moncontrol(0); #endif prg = argv[0]; n = SM_AQ_RCPTS; flags = 0; #if SM_HEAP_CHECK SmHeapCheck = 0; #endif while ((c = getopt(argc, argv, "aH:l: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 'l': Lookups = (uint) strtoul(optarg, NULL, 0); break; case 't': flags |= SMT_NOCHECKS; break; case 'V': ++Verbose; break; default: usage(prg); return EX_USAGE; } } sm_test_begin(argc, argv, "test adbr 2"); 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(); }