/*
 * Copyright (c) 2004 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-map-reopen-0.c,v 1.13 2005/09/26 23:32:18 ca Exp $")

#include "sm/error.h"
#include "sm/heap.h"
#include "sm/memops.h"
#include "sm/test.h"
#include "sm/maps.h"
#include "sm/mapc.h"
#include "sm/map.h"
#include "sm/mapclasses.h"
#include "sm/bdb.h"

#include "sm/io.h"

int Verbose = 0;

/*
caller must have created
MAPC_FILE: use before reopen()
and
MAPC_FILER: use after reopen()
the data in those files must be
MAPC_FILE:
left1:right1
left2:right2

MAPC_FILER:
left1:reopen1
left2:reopen2

MAPC_FILEB is used as "backup" filename for MAPC_FILE, i.e.,
the latter will be rename()d to the former.
*/

#define MAPC_TYPE	"hash"
#define MAPC_NAME	"bdbr0"
#define MAPC_FILE	"./bdbr0.db"
#define MAPC_FILER	"./bdbrr0.db"
#define MAPC_FILEB	"./bdbrb0.db"
#define MAPC_FILEF	"./bdbrf0.db"
#define KEY1	"left1"
#define KEY2	"left2"
#define KEY3	"left3"
#define DATA1	"right1"
#define DATA2	"right2"
#define DATAR1	"reopen1"
#define DATAR2	"reopen2"

static void
testh(bool fail)
{
	sm_ret_T ret;
	sm_maps_P maps;
	sm_map_P map;
	sm_cstr_P mtype, mname;
	sm_str_P lhs, rhs;
	sm_map_key_T key;
	int i;

	maps = NULL;
	mtype = mname = NULL;
	lhs = rhs = NULL;

	ret = sm_maps_init(&maps);
	SM_TEST(maps != NULL);
	if (maps == NULL)
		return;
	SM_TEST(sm_is_success(ret));

	mtype = sm_cstr_scpyn0((const uchar *)MAPC_TYPE, strlen(MAPC_TYPE));
	SM_TEST(mtype != NULL);
	if (mtype == NULL)
		goto error;

	mname = sm_cstr_scpyn0((const uchar *)MAPC_NAME, strlen(MAPC_NAME));
	SM_TEST(mname != NULL);
	if (mname == NULL)
		goto error;

	lhs = sm_str_new(NULL, 256, 1024);
	SM_TEST(lhs != NULL);
	if (lhs == NULL)
		goto error;

	rhs = sm_str_new(NULL, 256, 1024);
	SM_TEST(rhs != NULL);
	if (rhs == NULL)
		goto error;

	ret = sm_bdb_class_create(maps);
	SM_TEST(sm_is_success(ret));

	map = NULL;
	ret = sm_map_open(maps, mname, mtype, 0, MAPC_FILE, SMAP_MODE_RDWR,
			&map, SMPO_END);
	SM_CSTR_FREE(mtype);
	SM_CSTR_FREE(mname);
	SM_TEST(sm_is_success(ret));
	if (!sm_is_success(ret))
		goto error;

	/* perform some operations ... */

	sm_str_clr(rhs);
	sm_str_assign(key, NULL, (uchar *)KEY1, strlen(KEY1), strlen(KEY1));
	ret = sm_map_lookup(map, SMMAP_FL_NONE, &key, rhs);
	SM_TEST(sm_is_success(ret));

	sm_str_assign(key, NULL, (uchar *)KEY2, strlen(KEY2), strlen(KEY2));
	ret = sm_map_lookup(map, SMMAP_FL_NONE, &key, rhs);
	SM_TEST(sm_is_success(ret));

	sm_str_assign(key, NULL, (uchar *)KEY3, strlen(KEY3), strlen(KEY3));
	ret = sm_map_lookup(map, SMMAP_FL_NONE, &key, rhs);
	SM_TEST(!sm_is_success(ret));

	sm_str_clr(lhs);
	sm_str_clr(rhs);
	ret = sm_str_scat(lhs, KEY1);
	SM_TEST(sm_is_success(ret));
	ret = sm_map_rewrite(map, SMMAP_FL_NONE, lhs, rhs);
	SM_TEST(sm_is_success(ret));
	SM_TEST(strncmp(DATA1, (char *) sm_str_data(rhs), sm_str_getlen(rhs))
		== 0);

	sm_str_clr(lhs);
	sm_str_clr(rhs);
	ret = sm_str_scat(lhs, KEY2);
	SM_TEST(sm_is_success(ret));
	ret = sm_map_rewrite(map, SMMAP_FL_NONE, lhs, rhs);
	SM_TEST(sm_is_success(ret));
	SM_TEST(strncmp(DATA2, (char *) sm_str_data(rhs), sm_str_getlen(rhs))
		== 0);

	/* wait for a char on stdin */
/*
	i = sm_io_getc(smioin);
*/

	i = rename(MAPC_FILE, MAPC_FILEB);
	SM_TEST(i == 0);

	if (fail)
	{
		/* shouldn't exist anymore */
		(void) unlink(MAPC_FILE);
	}
	else
	{
		i = rename(MAPC_FILER, MAPC_FILE);
		SM_TEST(i == 0);
	}

	ret = sm_map_reopen(map, 0, SMPO_END);
	if (fail)
	{
		SM_TEST(sm_is_err(ret));
		if (!sm_is_err(ret))
			goto error;

		sm_str_clr(lhs);
		sm_str_clr(rhs);
		ret = sm_str_scat(lhs, KEY1);
		SM_TEST(sm_is_success(ret));
		ret = sm_map_rewrite(map, SMMAP_FL_NONE, lhs, rhs);
		SM_TEST(sm_is_err(ret));

		i = rename(MAPC_FILER, MAPC_FILE);
		SM_TEST(i == 0);

		ret = sm_map_reopen(map, 0, SMPO_END);
	}

	SM_TEST(sm_is_success(ret));
	if (!sm_is_success(ret))
		goto error;

	/* perform some operations ... */

	sm_str_clr(lhs);
	sm_str_clr(rhs);
	ret = sm_str_scat(lhs, KEY1);
	SM_TEST(sm_is_success(ret));
	ret = sm_map_rewrite(map, SMMAP_FL_NONE, lhs, rhs);
	SM_TEST(sm_is_success(ret));
	SM_TEST(strncmp(DATAR1, (char *) sm_str_data(rhs),
			sm_str_getlen(rhs)) == 0);

	sm_str_clr(lhs);
	sm_str_clr(rhs);
	ret = sm_str_scat(lhs, KEY2);
	SM_TEST(sm_is_success(ret));
	ret = sm_map_rewrite(map, SMMAP_FL_NONE, lhs, rhs);
	SM_TEST(sm_is_success(ret));
	SM_TEST(strncmp(DATAR2, (char *) sm_str_data(rhs),
			sm_str_getlen(rhs)) == 0);

	sm_str_clr(lhs);
	sm_str_clr(rhs);
	ret = sm_str_scat(lhs, KEY3);
	SM_TEST(sm_is_success(ret));
	ret = sm_map_lookup(map, SMMAP_FL_NONE, lhs, rhs);
	SM_TEST(sm_is_err(ret));

	ret = sm_map_close(map, 0);
	SM_TEST(sm_is_success(ret));

	ret = sm_maps_term(maps);
	SM_TEST(sm_is_success(ret));
	SM_STR_FREE(lhs);
	SM_STR_FREE(rhs);
	return;

  error:
	sm_maps_term(maps);
}


int
main(int argc, char *argv[])
{
	int c;
	bool fail;

	fail = false;
	while ((c = getopt(argc, argv, "f")) != -1)
	{
		switch (c)
		{
		  case 'f':
			fail = true;
			break;
		  default:
			return 1;
		}
	}
	sm_test_begin(argc, argv, "test map reopen 0");
	testh(fail);
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1