/*
 * Copyright (c) 2000-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-rpool.c,v 1.18 2005/04/14 17:14:02 ca Exp $")

#include <stdio.h>
#include "sm/assert.h"
#include "sm/debug.h"
#include "sm/heap.h"
#include "sm/rpool.h"
#include "sm/test.h"

#if SM_HEAP_CHECK
#include "sm/io.h"
extern SM_DEBUG_T SmHeapCheck;
# define HEAP_CHECK (SmHeapCheck > 0)
#else
# define HEAP_CHECK 0
#endif

static void	rfree(void *cx);

static int freeattachments = 0;

static void
rfree(cx)
	void *cx;
{
	SM_TEST(freeattachments > 0);
	--freeattachments;
	if (SmTestVerbose)
		(void) fprintf(stdout,"rfree freeing `%s'\n", (char *) cx);
}

#define TRPOOLS	26
#define RPMAXS	32768

#define M1	128
#define M2	256
#define M3	512
#define M4	1000

int
main(int argc, char *argv[])
{
	sm_rpool_P rpool;
	char *p, *np;
	char *a[TRPOOLS];
	int i, c;
	size_t s, l, j;
	sm_rpool_attach_T att;

#if SM_HEAP_CHECK
	SmHeapCheck = 0;
#endif
	while ((c = getopt(argc, argv, "H:")) != -1)
	{
		switch (c)
		{
#if SM_HEAP_CHECK
		  case 'H':
			SmHeapCheck = atoi(optarg);
			break;
#endif /* SM_HEAP_CHECK */
#if 0
		  default:
			usage(argv[0]);
			return(1);
#endif /* 0 */
		}
	}
	sm_test_begin(argc, argv, "test rpool");
	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	att = sm_rpool_attach(rpool, rfree, "attachment #1");
	SM_TEST(att != NULL);
	++freeattachments;
	for (i = 1; i < TRPOOLS; ++i)
	{
		size_t sz;

		sz = i * i * i;
		a[i] = sm_rpool_malloc(rpool, sz);
		SM_TEST(a[i] != NULL);
		if (a[i] == NULL)
		{
			fprintf(stderr, "failed for i=%d, sz=%d\n", i,
				(int) sz);
			goto err;
		}
		p = a[i];
		for (j = 0; j < sz; ++j)
			*p++ = 'a' + i;
	}
	att = sm_rpool_attach(rpool, rfree, "attachment #2");
	++freeattachments;
	(void) sm_rpool_attach(rpool, rfree, "attachment #3");
	++freeattachments;
	sm_rpool_detach(att);
	--freeattachments;
	sm_rpool_delete(rpool);
	SM_TEST(freeattachments == 0);

	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	sm_rpool_setsizes(rpool, 8192, 4096, RPMAXS);
	p = sm_rpool_malloc(rpool, RPMAXS);
	SM_TEST(p != NULL);
	sm_rpool_delete(rpool);

	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	p = sm_rpool_malloc(rpool, M1);
	SM_TEST(p != NULL);
	for (i = 0; i < M1; i++)
		p[i] = (uchar) i;
	for (i = 0; i < M1; i++)
		SM_TEST((uchar) p[i] == (uchar) i);
	np = sm_rpool_realloc(rpool, p, M1, M2);
	SM_TEST(np != NULL);
	for (i = 0; i < M1; i++)
		SM_TEST(np[i] == (uchar) i);
	for (i = M1; i < M2; i++)
		np[i] = (uchar) i;
	p = sm_rpool_realloc(rpool, np, M2, M3);
	SM_TEST(p != NULL);
	for (i = 0; i < M2; i++)
		SM_TEST((uchar) p[i] == (uchar) i);
	for (i = M2; i < M3; i++)
		p[i] = (uchar) i;
	np = sm_rpool_realloc(rpool, p, M3, M4);
	SM_TEST(np != NULL);
	for (i = 0; i < M3; i++)
		SM_TEST((uchar) np[i] == (uchar) i);
	sm_rpool_delete(rpool);

	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	sm_rpool_setsizes(rpool, 8192, 4096, RPMAXS);
	p = sm_rpool_malloc(rpool, RPMAXS + 1);
	SM_TEST(p == NULL);
	p = sm_rpool_malloc(rpool, RPMAXS / 2);
	SM_TEST(p != NULL);
	p = sm_rpool_malloc(rpool, RPMAXS / 2);
	SM_TEST(p != NULL);
	p = sm_rpool_malloc(rpool, 2);
	SM_TEST(p == NULL);
	sm_rpool_delete(rpool);

	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	sm_rpool_setsizes(rpool, 8192, 4096, RPMAXS);
	for (j = 0; j < RPMAXS / SM_ALIGN_SIZE; ++j)
	{
		p = sm_rpool_malloc(rpool, SM_ALIGN_SIZE);
		SM_TEST(p != NULL);
	}
	p = sm_rpool_malloc(rpool, 1);
	SM_TEST(p == NULL);

#if SM_HEAP_CHECK
	if (HEAP_CHECK)
	{
		sm_io_fprintf(smioout, "heap after filling up rpool:\n");
		sm_heap_report(smioout, 3);
	}
#endif /* SM_HEAP_CHECK */
	sm_rpool_delete(rpool);

	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	for (s = 10; s < 1000; s += 50)
	{
		p = sm_rpool_zalloc(rpool, s);
		SM_TEST(p != NULL);
		if (p != NULL)
		{
			char *ptr;

			ptr = p;
			for (l = 0; l < s; l++)
				SM_TEST(ptr[l] == '\0');
		}
	}
	sm_rpool_delete(rpool);


#if SM_HEAP_CHECK
	/* XXX more tests? */
	if (HEAP_CHECK)
	{
		sm_io_fprintf(smioout, "heap after freeing rpool:\n");
		sm_heap_report(smioout, 3);
	}
#endif /* SM_HEAP_CHECK */
  err:
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1