Mailing List Archive

[6.0] 5f8310330 varnishtest: Allow macros to be backed by functions
commit 5f8310330e157400b8b2a817d5b3cb91b05bf442
Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
Date: Thu Jun 17 15:49:45 2021 +0200

varnishtest: Allow macros to be backed by functions

Instead of having a mere value, these would be able to compute a macro
expansion. We parse the contents inside the ${...} delimiters as a VAV,
but there can't be (yet?) nested curly {braces}, even quoted.

The first argument inside the delimiters is the macro name, and other
VAV arguments are treated as arguments to the macro's function.

For example ${foo,bar,baz} would call the a macro "foo"'s function with
arguments "bar" and "baz". Simple macros don't take arguments and work
as usual.

Conflicts:
bin/varnishtest/vtc.c
bin/varnishtest/vtc_main.c

diff --git a/bin/varnishtest/vtc.c b/bin/varnishtest/vtc.c
index e9e178ccc..87ee0055b 100644
--- a/bin/varnishtest/vtc.c
+++ b/bin/varnishtest/vtc.c
@@ -75,6 +75,7 @@ struct macro {
VTAILQ_ENTRY(macro) list;
char *name;
char *val;
+ macro_f *func;
};

static VTAILQ_HEAD(,macro) macro_list = VTAILQ_HEAD_INITIALIZER(macro_list);
@@ -82,10 +83,10 @@ static VTAILQ_HEAD(,macro) macro_list = VTAILQ_HEAD_INITIALIZER(macro_list);
/**********************************************************************/

static struct macro *
-macro_def_int(const char *name, const char *fmt, va_list ap)
+macro_def_int(const char *name, macro_f *func, const char *fmt, va_list ap)
{
struct macro *m;
- char buf[256];
+ struct vsb *vsb;

VTAILQ_FOREACH(m, &macro_list, list)
if (!strcmp(name, m->name))
@@ -98,9 +99,18 @@ macro_def_int(const char *name, const char *fmt, va_list ap)
VTAILQ_INSERT_TAIL(&macro_list, m, list);
}
AN(m);
- vbprintf(buf, fmt, ap);
- REPLACE(m->val, buf);
- AN(m->val);
+ if (func != NULL) {
+ AZ(fmt);
+ m->func = func;
+ } else {
+ vsb = VSB_new_auto();
+ AN(vsb);
+ VSB_vprintf(vsb, fmt, ap);
+ AZ(VSB_finish(vsb));
+ REPLACE(m->val, VSB_data(vsb));
+ AN(m->val);
+ VSB_destroy(&vsb);
+ }
return (m);
}

@@ -111,12 +121,12 @@ macro_def_int(const char *name, const char *fmt, va_list ap)
*/

void
-extmacro_def(const char *name, const char *fmt, ...)
+extmacro_def(const char *name, macro_f *func, const char *fmt, ...)
{
va_list ap;

va_start(ap, fmt);
- (void)macro_def_int(name, fmt, ap);
+ (void)macro_def_int(name, func, fmt, ap);
va_end(ap);
}

@@ -132,8 +142,13 @@ init_macro(void)
struct macro *m;

/* Dump the extmacros for completeness */
- VTAILQ_FOREACH(m, &macro_list, list)
- vtc_log(vltop, 4, "extmacro def %s=%s", m->name, m->val);
+ VTAILQ_FOREACH(m, &macro_list, list) {
+ if (m->val != NULL)
+ vtc_log(vltop, 4,
+ "extmacro def %s=%s", m->name, m->val);
+ else
+ vtc_log(vltop, 4, "extmacro def %s(...)", m->name);
+ }

AZ(pthread_mutex_init(&macro_mtx, NULL));
}
@@ -155,7 +170,7 @@ macro_def(struct vtclog *vl, const char *instance, const char *name,

AZ(pthread_mutex_lock(&macro_mtx));
va_start(ap, fmt);
- m = macro_def_int(name, fmt, ap);
+ m = macro_def_int(name, NULL, fmt, ap);
va_end(ap);
vtc_log(vl, 4, "macro def %s=%s", name, m->val);
AZ(pthread_mutex_unlock(&macro_mtx));
@@ -191,35 +206,61 @@ void
macro_cat(struct vtclog *vl, struct vsb *vsb, const char *b, const char *e)
{
struct macro *m;
- int l;
- char *retval = NULL;
+ char **argv, *retval = NULL;
+ const char *err = NULL;
+ int argc;

AN(b);
if (e == NULL)
e = strchr(b, '\0');
AN(e);
- l = e - b;

- if (l == 4 && !memcmp(b, "date", l)) {
+ argv = VAV_ParseTxt(b, e, &argc, ARGV_COMMA);
+ AN(argv);
+
+ if (*argv != NULL)
+ vtc_fatal(vl, "Macro ${%.*s} parsing failed: %s",
+ (int)(e - b), b, *argv);
+
+ assert(argc >= 2);
+
+ if (!strcmp(argv[1], "date")) {
double t = VTIM_real();
retval = malloc(64);
AN(retval);
VTIM_format(t, retval);
VSB_cat(vsb, retval);
free(retval);
+ VAV_Free(argv);
return;
}

AZ(pthread_mutex_lock(&macro_mtx));
VTAILQ_FOREACH(m, &macro_list, list) {
CHECK_OBJ_NOTNULL(m, MACRO_MAGIC);
- if (!strncmp(b, m->name, l) && m->name[l] == '\0')
+ if (!strcmp(argv[1], m->name))
break;
}
- if (m != NULL)
- REPLACE(retval, m->val);
+ if (m != NULL) {
+ if (m->func != NULL) {
+ AZ(m->val);
+ retval = m->func(argc, argv, &err);
+ if (err == NULL)
+ AN(retval);
+ } else {
+ AN(m->val);
+ if (argc == 2)
+ REPLACE(retval, m->val);
+ else
+ err = "macro does not take arguments";
+ }
+ }
AZ(pthread_mutex_unlock(&macro_mtx));

+ if (err != NULL)
+ vtc_fatal(vl, "Macro ${%.*s} failed: %s",
+ (int)(e - b), b, err);
+
if (retval == NULL) {
if (!ign_unknown_macro)
vtc_fatal(vl, "Macro ${%.*s} not found",
@@ -230,6 +271,7 @@ macro_cat(struct vtclog *vl, struct vsb *vsb, const char *b, const char *e)

VSB_cat(vsb, retval);
free(retval);
+ VAV_Free(argv);
}

struct vsb *
diff --git a/bin/varnishtest/vtc.h b/bin/varnishtest/vtc.h
index 7c705bf29..868fe6884 100644
--- a/bin/varnishtest/vtc.h
+++ b/bin/varnishtest/vtc.h
@@ -121,8 +121,9 @@ struct vsb *macro_expand(struct vtclog *vl, const char *text);
struct vsb *macro_expandf(struct vtclog *vl, const char *, ...)
v_printflike_(2, 3);

-void extmacro_def(const char *name, const char *fmt, ...)
- v_printflike_(2, 3);
+typedef char* macro_f(int, char *const *, const char **);
+void extmacro_def(const char *name, macro_f *func, const char *fmt, ...)
+ v_printflike_(3, 4);

struct http;
void cmd_stream(CMD_ARGS);
diff --git a/bin/varnishtest/vtc_main.c b/bin/varnishtest/vtc_main.c
index 27754d04e..ca263aa61 100644
--- a/bin/varnishtest/vtc_main.c
+++ b/bin/varnishtest/vtc_main.c
@@ -161,7 +161,7 @@ parse_D_opt(char *arg)
if (!q)
return (0);
*q++ = '\0';
- extmacro_def(p, "%s", q);
+ extmacro_def(p, NULL, "%s", q);

return (1);
}
@@ -504,7 +504,8 @@ i_mode(void)

}
AN(topbuild);
- extmacro_def("topbuild", "%s", topbuild);
+ extmacro_def("topbuild", NULL, "%s", topbuild);
+
/*
* Build $PATH which can find all programs in the build tree
*/
@@ -571,7 +572,7 @@ ip_magic(void)
fd = VTCP_bind(sa, NULL);
assert(fd >= 0);
VTCP_myname(fd, abuf, sizeof abuf, pbuf, sizeof(pbuf));
- extmacro_def("localhost", "%s", abuf);
+ extmacro_def("localhost", NULL, "%s", abuf);

#if defined (__APPLE__)
/*
@@ -583,7 +584,7 @@ ip_magic(void)
#endif

/* Expose a backend that is forever down. */
- extmacro_def("bad_backend", "%s %s", abuf, pbuf);
+ extmacro_def("bad_backend", NULL, "%s %s", abuf, pbuf);

/*
* We need an IP number which will not repond, ever, and that is a
@@ -593,7 +594,7 @@ ip_magic(void)
* check your /proc/sys/net/ipv4/ip_nonlocal_bind setting.
*/

- extmacro_def("bad_ip", "%s", "192.0.2.255");
+ extmacro_def("bad_ip", NULL, "%s", "192.0.2.255");
}

/**********************************************************************
@@ -673,7 +674,7 @@ main(int argc, char * const *argv)
tmppath = strdup("/tmp");

cwd = getcwd(buf, sizeof buf);
- extmacro_def("pwd", "%s", cwd);
+ extmacro_def("pwd", NULL, "%s", cwd);

vmod_path = NULL;

_______________________________________________
varnish-commit mailing list
varnish-commit@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit