/*
* Copyright (c) 2002-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-idb-0.c,v 1.59 2007/06/18 04:42:31 ca Exp $")
#include "sm/io.h"
#include "sm/mta.h"
#include "sm/cstr.h"
#include "sm/cdb.h"
#include "sm/ibdb.h"
#include "sm/qmgr.h"
#include "sm/memops.h"
#include "sm/bhtable.h"
#include "sm/sysexits.h"
#include "sm/test.h"
#include "ibdb.h"
#include <stdio.h>
/*
** Test program to write and read IBDB.
** Uses wribdb.c to write IBDB.
*/
#define FNAME "ibd"
#define IBDBSIZE 8192
#define INIT_SEQ 1
static int init_seq = INIT_SEQ;
static uint n_trunc = 128;
static int Verbose = 0;
/*
** ToDo:
** - more consistency checks for read data.
** - cleanup files.
*/
#include "../checks/wribdb.c"
/*
** TESTIDBR -- read INCEDB records
**
** Parameters:
** base_dir -- name of base directory (can be NULL)
** iter -- number of iterations (transactions)
** maxs -- maximum size of an INCEDB file
**
** Returns:
** usual sm_error code.
*/
static sm_ret_T
testidbr(const char *base_dir, int iter, int maxs, uint flags)
{
int i, j, nrcpts, status;
ibdbr_ctx_P ibdbr_ctx;
ibdb_ta_P ibdb_ta;
ibdb_rcpt_P rcpt;
ibdb_hdrmod_P ibdb_hdrmod;
sessta_id_T ta_id;
id_count_T id_count;
sm_str_P str;
sm_ret_T ret;
uint32_t first, last;
char hdr[SM_MAXHDRLEN];
ibdb_ta = NULL;
rcpt = NULL;
str = NULL;
ibdbr_ctx = NULL;
last = 1;
ret = ibdbf_get_seq(base_dir, FNAME, IBDB_OFL_WRITE, &first, &last);
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return ret;
str = sm_str_new(NULL, 256, 256);
SM_TEST(str != NULL);
if (str == NULL)
goto end;
if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATE) &&
!WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATED))
{
int r;
struct stat sb;
off_t size;
const char *name;
crt_ibdb_path(str, IBDB_WR_DIR, FNAME, last);
name = (const char *) sm_str_getdata(str);
r = stat(name, &sb);
if (Verbose > 1)
sm_io_fprintf(smioerr,
"truncating=%s, r=%d, size=%ld\n",
name, r, sb.st_size);
SM_TEST(0 == r);
if (0 == r && (size = sb.st_size) > 0)
{
if (size > n_trunc)
size -= n_trunc;
else
--size;
r = truncate(name, size);
}
flags |= WRIBDB_FL_TRUNCATED;
}
ret = ibdbr_open(base_dir, FNAME, SM_IO_RDONLY, init_seq, maxs,
IBDB_OFL_WRITE, &ibdbr_ctx);
if (sm_is_err(ret) && sm_error_value(ret) == ENOENT)
{
ret = ibdbr_open(base_dir, FNAME, SM_IO_RDONLY, first, maxs,
IBDB_OFL_WRITE, &ibdbr_ctx);
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return ret;
}
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return ret;
ibdb_ta = (ibdb_ta_P) sm_zalloc(sizeof(*ibdb_ta));
SM_TEST(ibdb_ta != NULL);
if (ibdb_ta == NULL)
goto end;
ibdb_ta->ibt_ta_id = ta_id;
ibdb_ta->ibt_mail_pa = sm_str_new(NULL, 256, 256);
SM_TEST(ibdb_ta->ibt_mail_pa != NULL);
if (ibdb_ta->ibt_mail_pa == NULL)
goto end;
ibdb_hdrmod = (ibdb_hdrmod_P) sm_zalloc(sizeof(*ibdb_hdrmod));
SM_TEST(ibdb_hdrmod != NULL);
if (ibdb_hdrmod == NULL)
goto end;
ibdb_hdrmod->ibh_ta_id = ta_id;
rcpt = (ibdb_rcpt_P) sm_zalloc(sizeof(*rcpt));
SM_TEST(rcpt != NULL);
if (rcpt == NULL)
goto end;
rcpt->ibr_ta_id = ta_id;
rcpt->ibr_pa = sm_str_new(NULL, 256, 256);
SM_TEST(rcpt->ibr_pa != NULL);
if (rcpt->ibr_pa == NULL)
goto end;
id_count = 0;
if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_1OPENTA))
{
i = INT_MAX;
j = INT_MAX > 2;
sm_str_clr(str);
ret = sm_strprintf(str, "rcpt-%d-%d@other.Rcpt", i, j);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status);
SM_TEST_E(ret == RT_IBDB_RCPT);
SM_TEST_E(sm_memeq(sm_str_getdata(str),
sm_str_getdata(rcpt->ibr_pa),
sm_str_getlen(rcpt->ibr_pa)));
SM_TEST_E(rcpt->ibr_idx == (rcpt_idx_T) j);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status);
SM_TEST_E(ret == RT_IBDB_TA);
SM_CSTR_FREE(ibdb_ta->ibt_cdb_id);
}
for (i = 0; i < iter; i++)
{
id_count++;
nrcpts = (rcpts_per_ta > 0) ? rcpts_per_ta : (i % 5) + 1;
for (j = 0; j < nrcpts; j++)
{
sm_str_clr(str);
ret = sm_strprintf(str,
"rcpt-%d-%d@other.Rcpt", i, j);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod
, &status);
SM_TEST(ret == RT_IBDB_RCPT);
if (sm_is_err(ret))
goto end;
SM_TEST(sm_memeq(sm_str_getdata(str),
sm_str_getdata(rcpt->ibr_pa),
sm_str_getlen(rcpt->ibr_pa)));
SM_TEST(rcpt->ibr_idx == (rcpt_idx_T) j);
}
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status);
if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_LONG))
{
SM_TEST_E(RT_IBDB_HDRMOD == ret);
SM_TEST(SM_HM_TYPE_PREPEND == ibdb_hdrmod->ibh_type);
SM_TEST_E(NULL != long_str);
j = snprintf(long_str, long_str_len,
"HeaderPreLong: prepend ta=%s i=%d",
ta_id, i);
for (; j < long_str_len - 4; j++)
long_str[j] = '0' + (j % 10);
long_str[long_str_len - 4] ='\r';
long_str[long_str_len - 3] ='\n';
long_str[long_str_len - 2] ='\0';
SM_TEST(sm_memeq(long_str,
sm_cstr_data(ibdb_hdrmod->ibh_hdr),
sm_cstr_getlen(ibdb_hdrmod->ibh_hdr)));
SM_CSTR_FREE(ibdb_hdrmod->ibh_hdr);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod
, &status);
}
if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_HDR_PRE))
{
SM_TEST(RT_IBDB_HDRMOD == ret);
if (sm_is_err(ret))
break;
SM_TEST(SM_HM_TYPE_PREPEND == ibdb_hdrmod->ibh_type);
ret = snprintf(hdr, sizeof(hdr),
"HeaderPre: prepend ta=%s i=%d\r\n",
ta_id, i);
SM_TEST(sm_memeq(hdr,
sm_cstr_data(ibdb_hdrmod->ibh_hdr),
sm_cstr_getlen(ibdb_hdrmod->ibh_hdr)));
SM_CSTR_FREE(ibdb_hdrmod->ibh_hdr);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod
, &status);
}
if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_HDR_REM))
{
SM_TEST(RT_IBDB_HDRMOD == ret);
SM_TEST(SM_HM_TYPE_REMOVE == ibdb_hdrmod->ibh_type);
SM_TEST(2 == ibdb_hdrmod->ibh_pos);
SM_TEST(NULL == ibdb_hdrmod->ibh_hdr);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod
, &status);
}
if (WRIBDB_IS_FLAG(flags, WRIBDB_FL_HDR_APP))
{
SM_TEST(RT_IBDB_HDRMOD == ret);
SM_TEST(SM_HM_TYPE_APPEND == ibdb_hdrmod->ibh_type);
ret = snprintf(hdr, sizeof(hdr),
"HeaderApp: append ta=%s i=%d\r\n",
ta_id, i);
SM_TEST(sm_memeq(hdr,
sm_cstr_data(ibdb_hdrmod->ibh_hdr),
sm_cstr_getlen(ibdb_hdrmod->ibh_hdr)));
SM_CSTR_FREE(ibdb_hdrmod->ibh_hdr);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod
, &status);
}
SM_TEST(ret == RT_IBDB_TA);
if (sm_is_err(ret))
break;
/* check ta content?? */
SM_CSTR_FREE(ibdb_ta->ibt_cdb_id);
for (j = 0; j < nrcpts; j++)
{
sm_str_clr(str);
ret = sm_strprintf(str,
"rcpt-%d-%d@other.Rcpt", i, j);
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod
, &status);
SM_TEST(ret == RT_IBDB_RCPT);
if (sm_is_err(ret))
goto end;
SM_TEST(sm_memeq(sm_str_getdata(str),
sm_str_getdata(rcpt->ibr_pa),
sm_str_getlen(rcpt->ibr_pa)));
}
ret = ibdbr_get(ibdbr_ctx, rcpt, ibdb_ta, ibdb_hdrmod, &status);
if (sm_is_err(ret) &&
WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATE) &&
WRIBDB_IS_FLAG(flags, WRIBDB_FL_TRUNCATED))
{
SM_TEST(SM_IO_EOF == ret ||
sm_error_value(ret) == ENOENT ||
sm_error_perm(SM_EM_IO, EIO) == ret);
if (!(SM_IO_EOF == ret ||
sm_error_value(ret) == ENOENT ||
sm_error_perm(SM_EM_IO, EIO) == ret))
sm_io_fprintf(smioerr,
"sev=ERR, where=2, ibdbr_get%=#x\n"
, ret);
}
else
{
SM_TEST(ret == RT_IBDB_TA);
if (sm_is_err(ret))
break;
/* check ta content?? */
}
SM_CSTR_FREE(ibdb_ta->ibt_cdb_id);
}
end:
error:
if (ibdb_ta != NULL)
{
SM_STR_FREE(ibdb_ta->ibt_mail_pa);
sm_free(ibdb_ta);
}
if (rcpt != NULL)
{
SM_STR_FREE(rcpt->ibr_pa);
sm_free(rcpt);
}
SM_STR_FREE(str);
if (ibdbr_ctx != NULL)
{
ret = ibdbr_close(ibdbr_ctx);
SM_TEST(ret == SM_SUCCESS);
}
return ret;
}
static void
usage(const char *prg)
{
sm_io_fprintf(smioerr,
"usage: %s [options]\n"
"-1 write one (open) transaction at begin\n"
"-a test header append records\n"
"-I generate incomplete IBDB file\n"
"-i n n iterations\n"
"-l n use length n for header modification string\n"
"-m n maximum size of IBDB file\n"
"-p test header prepend records\n"
"-R test header removal records\n"
"-r read only\n"
"-t n truncate last IBDB file by n bytes before reading\n"
"-V increase verbosity\n"
"-w write only\n"
, prg);
exit(EX_USAGE);
}
int
main(int argc, char *argv[])
{
int iter, c, maxs;
sm_ret_T ret;
uint flags;
bool readonly;
bool writeonly;
bool incomplete;
char *base_dir;
iter = 100;
flags = 0;
maxs = IBDBSIZE;
readonly = false;
writeonly = false;
incomplete = false;
base_dir = NULL;
while ((c = getopt(argc, argv, "1ab:HIi:l:m:n:pRrt:Vw")) != -1)
{
switch (c)
{
case '1':
flags |= WRIBDB_FL_1OPENTA;
break;
case 'a':
flags |= WRIBDB_FL_HDR_APP;
break;
case 'b':
base_dir = strdup(optarg);
if (NULL == base_dir)
return EX_OSERR;
break;
#if SM_HEAP_CHECK
case 'H':
SmHeapCheck = atoi(optarg);
break;
#endif
case 'I':
incomplete = true;
flags |= WRIBDB_FL_INCOMPL;
break;
case 'i':
iter = strtol(optarg, NULL, 0);
if (iter <= 0)
return EX_USAGE;
break;
case 'l':
long_str_len = strtol(optarg, NULL, 0);
if (long_str_len <= 256)
return EX_USAGE;
flags |= WRIBDB_FL_LONG;
break;
case 'm':
maxs = strtol(optarg, NULL, 0);
if (maxs <= 0)
return EX_USAGE;
break;
case 'n':
rcpts_per_ta = strtol(optarg, NULL, 0);
if (rcpts_per_ta <= 0)
return EX_USAGE;
break;
case 'p':
flags |= WRIBDB_FL_HDR_PRE;
break;
case 'R':
flags |= WRIBDB_FL_HDR_REM;
break;
case 'r':
readonly = true;
break;
case 't':
n_trunc = strtoul(optarg, NULL, 0);
if (n_trunc <= 0)
return EX_USAGE;
flags |= WRIBDB_FL_TRUNCATE;
break;
case 'V':
++Verbose;
break;
case 'w':
writeonly = true;
break;
default:
usage(argv[0]);
/* NOTREACHED */
return EX_USAGE;
}
}
sm_test_begin(argc, argv, "test sm_idb_0");
if (readonly)
ret = SM_SUCCESS;
else
ret = testidbwr(base_dir, iter, maxs, flags, NULL, NULL);
if (ret == SM_SUCCESS && !incomplete && !writeonly)
ret = testidbr(base_dir, iter, maxs, flags);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1