/*
 * 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.
 */

/*
**  Test s*printf() functions
*/

#include "sm/generic.h"
SM_IDSTR(id, "@(#)$Id: t-printf.c,v 1.24 2007/11/18 05:38:31 ca Exp $")

#include "sm/limits.h"
#include "sm/string.h"
#include "sm/base64.h"
#include "sm/io.h"
#include "sm/str.h"
#include "sm/rpool.h"
#include "sm/types.h"
#include "sm/net.h"
#include "sm/test.h"
#include <stdio.h>	/* for snprintf() prototype */

static void
cmp(char *s1, char *s2, int line)
{
	if (!SM_TEST(strcmp(s1, s2) == 0))
		(void) sm_io_fprintf(smioerr,
			"%3d: got   \"%s\"\ninstead of \"%s\"\n",
			line, s1, s2);
}

#define MAXL	128
#define STRL	16

static void
test(sm_rpool_P rpool)
{
	int i;
	sm_str_P str;
	char *r;
	char buf[MAXL];
	char buf2[MAXL];
	sm_file_T file;

	memset(buf, (int) 'X', sizeof(buf));
	memset(buf2, (int) 'X', sizeof(buf2));
	str = sm_str_new(rpool, STRL, MAXL);
	SM_TEST(str != NULL);
	if (str == NULL)
		return;
	i = sm_str2file(str, &file);
	SM_TEST(i == SM_SUCCESS);
	if (i != SM_SUCCESS)
		return;

	sm_strprintf(str, "%d", 0);
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%S", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_io_fprintf(&file, "%d", 0);
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%S", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

#if HAVE_SNPRINTF
	sm_str_clr(str);
	sm_strprintf(str, "%d%cend", 0, '\0');
	snprintf(buf2, sizeof(buf2), "%d%cend", 0, '\0');
	i = sm_snprintf(buf, sizeof(buf), "%S", str);
	SM_TEST(i > 1);
	cmp(buf, buf2, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "%d%c", 0, '\0');
	snprintf(buf2, sizeof(buf2), "%d%c", 0, '\0');
	i = sm_snprintf(buf, sizeof(buf), "%S", str);
	SM_TEST(i > 1);
	cmp(buf, buf2, __LINE__);
#endif /* HAVE_SNPRINTF */

	sm_str_clr(str);
	sm_strprintf(str, "%d%c", 0, '\0');
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%N", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_io_fprintf(&file, "%d%c", 0, '\0');
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%N", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "%d\r\n%c", 0, '\0');
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "%d\r\n%c", 0, '\0');
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%#T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "%d\n\r%c", 0, '\0');
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "%d\r%c", 0, '\0');
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "0\r");
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "0\n");
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "%d\r\n", 0);
	r = "0";
	i = sm_snprintf(buf, sizeof(buf), "%#T", str);
	SM_TEST(i == 1);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "Too busy\r\n");
	r = "Too busy";
	i = sm_snprintf(buf, sizeof(buf), "%T", str);
	SM_TEST(i == 8);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	sm_strprintf(str, "Too busy\r\n\0");
	r = "Too busy";
	i = sm_snprintf(buf, sizeof(buf), "%#T", str);
	SM_TEST(i == 8);
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	r = "1234567890abcdefghijklmnopqrstuvwxyz";
	i = sm_str_scat(str, r);
	SM_TEST(i == SM_SUCCESS);
	i = sm_snprintf(buf, sizeof(buf), "%S", str);
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "-%S", str);
	SM_TEST(i == (int) strlen(r) + 1);
	cmp(buf + 1, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "0987654321%S", str);
	SM_TEST(i == (int) strlen(r) + 10);
	cmp(buf + 10, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%.10S", str);
	SM_TEST(i == 10);
	r = "1234567890";
	cmp(buf, r, __LINE__);

	r = NULL;
	i = sm_snprintf(buf, sizeof(buf), "%p %d", r, 5);
	SM_TEST(i == 5);
	r = "0x0 5";
	cmp(buf, r, __LINE__);

	r = NULL;
	i = sm_snprintf(buf, sizeof(buf), "%p %d %s", r, 5, "abc");
	SM_TEST(i == 9);
	r = "0x0 5 abc";

	r = NULL;
	i = sm_snprintf(buf, sizeof(buf), "test %p (%s:%d)", r, "abc", 5);
	SM_TEST(i == 16);
	r = "test 0x0 (abc:5)";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%r", 5);
	SM_TEST(i == 1);
	r = "5";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%r", 421);
	SM_TEST(i == 3);
	r = "421";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%r", (uint32_t) 0x80000001);
	SM_TEST(i == 10);
	r = "0x80000001";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%r", (uint32_t) 0x8030003a);
	SM_TEST(i == 10);
	r = "0x8030003a";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%A", ntohl(0x7F000001));
	r = "127.0.0.1";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%A", ntohl(0xFF139DFE));
	r = "255.19.157.254";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%#s", "abc");
	r = "abc";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%#s", "ab\tc");
	r = "ab%09c";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%#s", "ab%c");
	r = "ab%25c";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%#s", "ab\tc\001");
	r = "ab%09c%01";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%#.3s", "ab\tc\001");
	r = "ab_";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);


	i = sm_snprintf(buf, sizeof(buf), "%@s", "abc");
	r = "abc";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%@s", "ab\tc");
	r = "ab%09c";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%@s", "ab%c");
	r = "ab%25c";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%@s", "a bc");
	r = "a bc";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%@s", "ab\t c");
	r = "ab%09 c";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%@s", "ab%c ");
	r = "ab%25c ";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%@s", "ab, c");
	r = "ab%2C c";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "f1=%@s, f2=%@s", "ab, c", "d\t, e");
	r = "f1=ab%2C c, f2=d%09%2C e";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "f1=%@s, f2=%@s, f3=%@s",
		"ab, c", "d\t, e", "x,y,z  ,,");
	r = "f1=ab%2C c, f2=d%09%2C e, f3=x%2Cy%2Cz  %2C%2C";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);


	sm_str_clr(str);
	i = sm_str_scat(str, "ab%c");
	SM_TEST(i == SM_SUCCESS);
	i = sm_snprintf(buf, sizeof(buf), "%#.3S", str);
	r = "ab_";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);
	i = sm_snprintf(buf, sizeof(buf), "%#.3N", str);
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	i = sm_str_scat(str, "ab\tc\001");
	i = sm_snprintf(buf, sizeof(buf), "%#S", str);
	r = "ab%09c%01";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, 2, "%s", "abcdef");
	r = "a";
	SM_TEST(i == 6);
	cmp(buf, r, __LINE__);

	SM_ASSERT(MAXL >= 10);
	i = sm_snprintf(buf, 10, "%#S", str);
	r = "ab%09c%01";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	SM_ASSERT(MAXL >= 8);
	i = sm_snprintf(buf, 8, "%#S", str);
	r = "ab%09c_";
	SM_TEST(i == 9);
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, 8, "%#S", str);
	r = "ab%09c_";
	SM_TEST(i == 9);
	cmp(buf, r, __LINE__);


	i = sm_snprintf(buf, sizeof(buf), "%#N", str);
	r = "ab%09c%01";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);


	sm_str_clr(str);
	i = sm_str_scat(str, "ab%c");
	SM_TEST(i == SM_SUCCESS);
	i = sm_snprintf(buf, sizeof(buf), "%@.3S", str);
	r = "ab_";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);
	i = sm_snprintf(buf, sizeof(buf), "%@.3N", str);
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	sm_str_clr(str);
	i = sm_str_scat(str, "a  b\tc ");
	i = sm_snprintf(buf, sizeof(buf), "%@S", str);
	r = "a  b%09c ";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);
	i = sm_snprintf(buf, sizeof(buf), "%@N", str);
	r = "a  b%09c ";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);


	sm_str_clr(str);
	i = sm_snprintf(buf, sizeof(buf), "%Y", 0);
	r = "0";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 1);
	r = "1";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 16);
	buf2[0] = SM_B64DIGS[16];
	buf2[1] = '\0';
	cmp(buf, buf2, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 31);
	buf2[0] = SM_B64DIGS[31];
	buf2[1] = '\0';
	cmp(buf, buf2, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 32);
	buf2[0] = SM_B64DIGS[32];
	buf2[1] = '\0';
	cmp(buf, buf2, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 63);
	buf2[0] = SM_B64DIGS[63];
	buf2[1] = '\0';
	cmp(buf, buf2, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 64);
	r = "10";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 127);
	i = sm_snprintf(buf, sizeof(buf), "%Y", 128);
	r = "20";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 255);
	i = sm_snprintf(buf, sizeof(buf), "%Y", 256);
	r = "40";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 1023);
	i = sm_snprintf(buf, sizeof(buf), "%Y", 1024);
	r = "G0";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 4095);
	i = sm_snprintf(buf, sizeof(buf), "%Y", 4096);
	r = "100";
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%Y", 0x7FFFFFFF);
	SM_TEST(i == 6);
	i = sm_snprintf(buf, sizeof(buf), "%Y", 0xFFFFFFFF);
	SM_TEST(i == 6);

#if 0
	i = sm_asprintf(&s, "%r", 421);
	SM_TEST(i == 3);
	r = "421";
	cmp(s, r, __LINE__);
	sm_free(s);

	r = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
	i = sm_asprintf(&s, "%s", r);
	cmp(s, r, __LINE__);
	sm_free(s);
#endif

	i = sm_snprintf(buf, sizeof(buf), "%#c", '\t');
	r = "%09";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	i = sm_snprintf(buf, sizeof(buf), "%#c", 't');
	r = "t";
	SM_TEST(i == (int) strlen(r));
	cmp(buf, r, __LINE__);

	sm_str_free(str);
}

int
main(int argc, char *argv[])
{
	sm_rpool_P rpool;

	sm_test_begin(argc, argv, "test printf");
	test(NULL);
	rpool = sm_rpool_new(NULL);
	SM_TEST(rpool != NULL);
	if (rpool != NULL)
	{
		test(rpool);
		sm_rpool_delete(rpool);
	}
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1