/*
* Copyright (c) 2004-2006 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_RCSID("@(#)$Id: t-cdb-0.c,v 1.15 2006/07/18 02:43:18 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/io.h"
#include "sm/sysexits.h"
#include "sm/cdb.h"
#if TEST_CDB_BC
#include "cdbbf.h"
#endif
#include "sm/test.h"
#define SM_BUF_SIZE (4 * 1024)
#define SM_BF_SIZE (8 * 1024)
#if TEST_CDB_BC
extern sm_stream_T SmCDBStL;
# define CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, mode, instance, cdb_id) cdb_open_wr_vector(cdb_ctx, ta_id, dfp, mode, instance, &SmCDBStL, SM_BF_SIZE, cdb_id)
#else
# define CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, mode, instance, cdb_id) cdb_open_write(cdb_ctx, ta_id, dfp, mode, instance, cdb_id)
#endif
/*
** CDB_TEST -- simple CDB test
**
** Parameters:
** base -- base name for CDB
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
cdb_test(const char *base)
{
size_t i;
sm_ret_T ret;
cdb_ctx_P cdb_ctx;
cdb_id_P cdb_id;
sm_file_T *dfp;
ssize_t byteswritten, bytesread;
#if TEST_CDB_BC
sm_file_T *dfpr;
int r;
struct stat sb;
#endif
sessta_id_T ta_id;
uchar wbuf[SM_BUF_SIZE], wbuf2[SM_BUF_SIZE], rbuf[SM_BUF_SIZE];
dfp = NULL;
cdb_id = NULL;
SM_ASSERT(sizeof(rbuf) == sizeof(wbuf));
ret = cdb_start(base, &cdb_ctx);
SM_TEST_E(SM_SUCCESS == ret);
for (i = 0; i < sizeof(wbuf); i++)
{
wbuf[i] = 'A' + (i % 32);
wbuf2[i] = '0' + (i % 32);
if (i % 78 == 0)
wbuf[i] = wbuf2[i] = '\n';
}
sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT,
(ulonglong_T) 1, 2);
ret = CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, SM_IO_WREXCL, 0, &cdb_id);
SM_TEST_E(SM_SUCCESS == ret);
/* write some stuff ... */
ret = cdb_write(cdb_ctx, dfp, (uchar *) wbuf, sizeof(wbuf),
&byteswritten);
SM_TEST_E(SM_SUCCESS == ret);
SM_TEST(byteswritten == sizeof(wbuf));
#if TEST_CDB_BC
SM_TEST_E(cdb_id != NULL);
r = stat(cdbf_path(dfp), &sb);
SM_TEST(r < 0);
SM_TEST(ENOENT == errno);
#endif
ret = cdb_commit(cdb_ctx, dfp);
SM_TEST(SM_SUCCESS == ret);
#if TEST_CDB_BC
SM_TEST_E(cdb_id != NULL);
r = stat(cdbf_path(dfp), &sb);
SM_TEST(0 == r);
#endif
ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE);
SM_TEST(SM_SUCCESS == ret);
#if !TEST_CDB_BC
/* fails, file exists */
ret = cdb_open_write(cdb_ctx, ta_id, dfp, SM_IO_WREXCL, 0, NULL);
SM_TEST(ret != SM_SUCCESS);
if (!sm_is_err(ret))
{
cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE);
goto end;
}
#endif
/* open another instance */
ret = CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, SM_IO_WREXCL, 1, &cdb_id);
SM_TEST_E(SM_SUCCESS == ret);
SM_TEST_E(cdb_id != NULL);
/* write some stuff ... */
ret = cdb_write(cdb_ctx, dfp, (uchar *) wbuf2, sizeof(wbuf2),
&byteswritten);
SM_TEST(SM_SUCCESS == ret);
SM_TEST(byteswritten == sizeof(wbuf2));
ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE);
SM_TEST(SM_SUCCESS == ret);
/* try to read */
ret = cdb_open_read(cdb_ctx, ta_id, dfp);
SM_TEST_E(SM_SUCCESS == ret);
SM_TEST_E(dfp != NULL);
ret = sm_io_read(dfp, rbuf, sizeof(rbuf), &bytesread);
SM_TEST(SM_SUCCESS == ret);
SM_TEST(bytesread == sizeof(rbuf));
for (i = 0; i < sizeof(rbuf); i++)
{
SM_TEST(wbuf[i] == rbuf[i]);
if (wbuf[i] != rbuf[i])
break;
}
ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE);
SM_TEST(SM_SUCCESS == ret);
ret = cdb_unlink(cdb_ctx, ta_id);
SM_TEST(SM_SUCCESS == ret);
/* try to read 2nd instance */
ret = cdb_open_read(cdb_ctx, (char *)sm_cstr_data(cdb_id), dfp);
SM_TEST(SM_SUCCESS == ret);
SM_TEST_E(dfp != NULL);
ret = sm_io_read(dfp, rbuf, sizeof(rbuf), &bytesread);
SM_TEST(SM_SUCCESS == ret);
SM_TEST(bytesread == sizeof(rbuf));
for (i = 0; i < sizeof(rbuf); i++)
{
SM_TEST(wbuf2[i] == rbuf[i]);
if (wbuf2[i] != rbuf[i])
break;
}
ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE);
SM_TEST(SM_SUCCESS == ret);
ret = cdb_unlink(cdb_ctx, (char *)sm_cstr_data(cdb_id));
SM_TEST(SM_SUCCESS == ret);
#if TEST_CDB_BC
sm_snprintf(ta_id, sizeof(ta_id), SMTPS_STID_FORMAT,
(ulonglong_T) 2, 3);
ret = CDB_OPEN_WRITE(cdb_ctx, ta_id, dfp, SM_IO_RDWRCRX, 0, &cdb_id);
SM_TEST_E(SM_SUCCESS == ret);
/* write some stuff ... */
ret = cdb_write(cdb_ctx, dfp, (uchar *) wbuf, sizeof(wbuf),
&byteswritten);
SM_TEST(SM_SUCCESS == ret);
SM_TEST(byteswritten == sizeof(wbuf));
SM_TEST_E(cdb_id != NULL);
r = stat(cdbf_path(dfp), &sb);
SM_TEST(r < 0);
SM_TEST(ENOENT == errno);
ret = sm_io_dup(dfp);
SM_TEST(SM_SUCCESS == ret);
dfpr = dfp;
ret = sm_io_seek(dfpr, 0, SM_IO_SEEK_SET);
SM_TEST(SM_SUCCESS == ret);
ret = sm_io_read(dfpr, rbuf, sizeof(rbuf), &bytesread);
SM_TEST(SM_SUCCESS == ret);
SM_TEST(bytesread == sizeof(rbuf));
for (i = 0; i < sizeof(rbuf); i++)
{
SM_TEST(wbuf[i] == rbuf[i]);
if (wbuf[i] != rbuf[i])
break;
}
#if 0
ret = cdb_commit(cdb_ctx, dfp);
SM_TEST(SM_SUCCESS == ret);
SM_TEST_E(cdb_id != NULL);
r = stat(cdbf_path(dfp), &sb);
SM_TEST(0 == r);
#endif /* 0 */
ret = cdb_close(cdb_ctx, dfp, SM_IO_CF_NONE);
SM_TEST(SM_SUCCESS == ret);
ret = cdb_close(cdb_ctx, dfpr, SM_IO_CF_NONE);
SM_TEST(SM_SUCCESS == ret);
#endif /* TEST_CDB_BC */
error:
#if !TEST_CDB_BC
end:
#endif
ret = cdb_end(cdb_ctx);
SM_TEST(SM_SUCCESS == ret);
return ret;
}
/*
** USAGE -- usage message
**
** Parameters:
** prg -- program name
**
** Returns:
** none
*/
static void
usage(char *prg)
{
sm_io_fprintf(smioerr, "usage: %s [options]\n"
"perform CDB checks\n"
"-b name set base of CDB directory, default: empty\n"
" must be empty [= current directory] or end in '/'\n"
, prg
);
return;
}
int
main(int argc, char *argv[])
{
int c;
char *base;
base = "";
while ((c = getopt(argc, argv, "b:")) != -1)
{
switch (c)
{
case 'b':
base = strdup(optarg);
SM_TEST(base != NULL);
if (NULL == base)
return EX_OSERR;
break;
default:
usage(argv[0]);
return EX_USAGE;
}
}
sm_test_begin(argc, argv, "test cdb 0");
cdb_test(base);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1