/*
* Copyright (c) 2005, 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-strexpmac.c,v 1.4 2006/01/05 22:41:55 ca Exp $")
#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/error.h"
#include "sm/rpool.h"
#include "sm/test.h"
#include "sm/str.h"
#include "sm/strexp.h"
#include "sm/io.h"
extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
#define SMAXLEN 1024
static int Verbose = 0;
#define NMACROS 10
#if TEST_STREXPMAC_CB
#define sm_str_expmac(src, dst, f, n, macros, repl) \
sm_str_expmac_cb(src, dst, f, expmac, &t_ctx)
struct t_ctx_S
{
uint t_nmacros;
sm_str_P *t_macros;
sm_str_P *t_repl;
};
typedef struct t_ctx_S t_ctx_T, *t_ctx_P;
static sm_ret_T
expmac(const sm_str_P src, uint len, sm_str_P dst, uint mac_begin, uint mac_end, void *ctx)
{
sm_ret_T ret;
uint idx;
t_ctx_P t_ctx;
SM_REQUIRE(ctx != NULL);
t_ctx = (t_ctx_P)ctx;
ret = sm_find_macro(src, len, mac_begin, mac_end, &idx,
t_ctx->t_nmacros, t_ctx->t_macros);
if (sm_is_err(ret))
return ret;
if (idx < NMACROS && t_ctx->t_repl[idx] != NULL)
{
ret = sm_str_cat(dst, t_ctx->t_repl[idx]);
if (sm_is_err(ret))
return ret;
return 1;
}
return ret;
}
#endif /* TEST_STREXPMAC_CB */
static void
test_harness(sm_rpool_P a)
{
uint argc;
sm_str_P src, dst, macros[NMACROS], repl[NMACROS];
sm_ret_T ret;
#if TEST_STREXPMAC_CB
t_ctx_T t_ctx;
#endif /* TEST_STREXPMAC_CB */
#if TEST_STREXPMAC_CB
t_ctx.t_nmacros = 1;
t_ctx.t_macros = macros;
t_ctx.t_repl = repl;
#endif /* TEST_STREXPMAC_CB */
src = sm_str_new(a, SMAXLEN, SMAXLEN);
SM_TEST(src != NULL);
if (src == NULL)
return;
dst = sm_str_new(a, SMAXLEN, SMAXLEN);
SM_TEST(dst != NULL);
if (dst == NULL)
return;
for (argc = 0; argc < NMACROS; argc++)
{
macros[argc] = sm_str_new(a, SMAXLEN, SMAXLEN);
SM_TEST(macros[argc] != NULL);
if (macros[argc] == NULL)
return;
sm_strprintf(macros[argc], "macro%u", argc);
repl[argc] = sm_str_new(a, SMAXLEN, SMAXLEN);
SM_TEST(repl[argc] != NULL);
if (repl[argc] == NULL)
return;
sm_strprintf(repl[argc], "repl%uace", argc);
}
/* simple expansion */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "strrepl0ace") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* simple expansion */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "repl0ace") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* expansion suppressed */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "${macro0}") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* expansion suppressed */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\\\\\${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "\\\\${macro0}") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* expansion */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\\\${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "\\\\repl0ace") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* macro is not "defined", replaced with empty string */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str${macro}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 1);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "str") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* expansion fails */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str${macro");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 0);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "str${macro") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str$${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 1);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "str$repl0ace") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str$${macro0}${}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 1);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "str$repl0ace${}") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str$${macro0}${A}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 2);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "str$repl0ace") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str${macro0\\}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 1);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "str") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "str${macro0}${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 2);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "strrepl0acerepl0ace")
== 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "${macro1}X${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
#if TEST_STREXPMAC_CB
t_ctx.t_nmacros = 2;
#endif
ret = sm_str_expmac(src, dst, 0, 2, macros, repl);
SM_TEST(ret == 2);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "repl1aceXrepl0ace")
== 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "${macro1}X${macro0}");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
#if TEST_STREXPMAC_CB
t_ctx.t_nmacros = 1;
#endif
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 2);
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "Xrepl0ace")
== 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "ret=%r, dst='%S'\n", ret, dst);
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 0);
if (!sm_is_success(ret))
return;
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\$\\");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret > 0);
if (!sm_is_success(ret))
return;
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\a");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 0);
if (!sm_is_success(ret))
return;
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "\\\\");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expmac(src, dst, 0, 1, macros, repl);
SM_TEST(ret == 0);
if (!sm_is_success(ret))
return;
#if 0
/* two expansions and keep '%%' */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "%0-%%-%1");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expdig(src, dst, '\0', 2, argv);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!-%-arg-1!") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* keep '%%', one expansion does not have an argument */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "%0-%%-%1");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expdig(src, dst, '\0', 1, argv);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!-%-") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* two expansions and keep trailing '%' */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "%0-%1-%");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expdig(src, dst, '\0', 2, argv);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst), "arg-0!-arg-1!-%") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
/* many expansions */
sm_str_clr(src);
sm_str_clr(dst);
ret = sm_str_scat0(src, "%0.%1.%2.%3.%4.%5.%6.%7.%8.%9.%A");
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
return;
ret = sm_str_expdig(src, dst, '\0', 10, argv);
SM_TEST(sm_is_success(ret));
if (!sm_is_success(ret))
return;
SM_TEST(strcmp((char *)sm_str_getdata(dst),
"arg-0!.arg-1!.arg-2!.arg-3!.arg-4!.arg-5!.arg-6!.arg-7!.arg-8!.arg-9!.A") == 0);
if (Verbose > 2)
sm_io_fprintf(smioerr, "dst='%S'\n", dst);
#endif
for (argc = 0; argc < NMACROS; argc++)
{
SM_STR_FREE(macros[argc]);
SM_STR_FREE(repl[argc]);
}
sm_str_free(src);
sm_str_free(dst);
}
int
main(int argc, char *argv[])
{
int c;
sm_rpool_P a;
while ((c = getopt(argc, argv, "V")) != -1)
{
switch (c)
{
case 'V':
++Verbose;
break;
default:
/* usage(prg); */
break;
}
}
sm_test_begin(argc, argv, "test strexpmac()");
argc -= optind;
argv += optind;
/* create an rpool for entire test */
a = sm_rpool_new(NULL);
SM_TEST(a != NULL);
test_harness(a);
sm_rpool_delete(a);
/* test without rpool */
test_harness(NULL);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1