[master] 70b7d5840 vav: Add a test driver

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Fri Jul 2 16:22:04 UTC 2021


commit 70b7d584064f23694c37c41ed1ed60468458394f
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Fri Jul 2 17:50:02 2021 +0200

    vav: Add a test driver
    
    It started with one corner case, then I found more, then I found new
    potential corner cases introduced by my own attempts at squaring them.
    
    I decided to take a step back and start some VAV test coverage. With
    something not too complicated to edit, dealing with the corner cases
    should increase confidence with the introduction of new cases easy
    to review.

diff --git a/lib/libvarnish/Makefile.am b/lib/libvarnish/Makefile.am
index 3be8609f1..6d27522fb 100644
--- a/lib/libvarnish/Makefile.am
+++ b/lib/libvarnish/Makefile.am
@@ -46,10 +46,14 @@ libvarnish_la_SOURCES = \
 
 libvarnish_la_LIBADD = @PCRE_LIBS@
 
-TESTS = vjsn_test vnum_c_test vbh_test vsb_test
+TESTS = vav_test vjsn_test vnum_c_test vbh_test vsb_test
 
 noinst_PROGRAMS = ${TESTS}
 
+vav_test_SOURCES = vav.c
+vav_test_CFLAGS = $(AM_CFLAGS) -DTEST_DRIVER
+vav_test_LDADD = $(AM_LDFLAGS) libvarnish.la
+
 vbh_test_SOURCES	= vbh.c
 vbh_test_CFLAGS = $(AM_CFLAGS) -DTEST_DRIVER
 vbh_test_LDADD = $(AM_LDFLAGS) libvarnish.la
diff --git a/lib/libvarnish/vav.c b/lib/libvarnish/vav.c
index bc3eaf2cc..c3e91f2dd 100644
--- a/lib/libvarnish/vav.c
+++ b/lib/libvarnish/vav.c
@@ -303,3 +303,115 @@ main(int argc, char **argv)
 	return (0);
 }
 #endif
+
+#ifdef TEST_DRIVER
+#  include <stdio.h>
+
+struct test_case {
+	int		flag;
+	const char	*str;
+	const char	**argv;
+};
+
+static const struct test_case *tests[] = {
+#define TEST_PASS(flag, str, ...)					\
+	&(const struct test_case){flag, str,				\
+	    (const char **)&(const void *[]){NULL, __VA_ARGS__, NULL}}
+#define TEST_FAIL(flag, str, err)					\
+	&(const struct test_case){flag, str,				\
+	    (const char **)&(const void *[]){err_ ## err, NULL}}
+#define K ARGV_COMMENT
+#define C ARGV_COMMA
+#define N ARGV_NOESC
+	TEST_PASS(K|C|N, "", NULL),
+	TEST_PASS(0    , "foo", "foo"),
+	TEST_PASS(0    , "foo bar", "foo", "bar"),
+	TEST_PASS(  C  , "foo bar", "foo", "bar"),
+	TEST_PASS(  C  , "foo,bar", "foo", "bar"),
+	TEST_PASS(0    , "  foo  bar  ", "foo", "bar"),
+	TEST_PASS(0    , "foo \"bar baz\"", "foo", "bar baz"),
+	TEST_PASS(0    , "foo #bar", "foo", "#bar"),
+	TEST_PASS(K    , "foo #bar", "foo"),
+	TEST_PASS(    N, "\\", "\\"),
+	TEST_FAIL(0    , "\"foo", missing_quote),
+	NULL
+#undef N
+#undef C
+#undef K
+#undef TEST_FAIL
+#undef TEST_PASS
+};
+
+static char **
+test_run(const struct test_case *tc, int *ret)
+{
+	const char *exp, *act;
+	char **argv, *tmp;
+	int argc, i;
+
+	i = strlen(tc->str);
+	if (i == 0) {
+		argv = VAV_Parse(tc->str, &argc, tc->flag);
+	} else {
+		tmp = malloc(i); /* sanitizer-friendly */
+		AN(tmp);
+		memcpy(tmp, tc->str, i);
+		argv = VAV_ParseTxt(tmp, tmp + i, &argc, tc->flag);
+		free(tmp);
+	}
+	AN(argv);
+
+	if (tc->argv[0] != argv[0]) {
+		exp = tc->argv[0] != NULL ? tc->argv[0] : "success";
+		act = argv[0] != NULL ? argv[0] : "success";
+		printf(
+		    "ERROR: Parsing string <%s> with flags %x, "
+		    "expected <%s> got <%s>.\n",
+		    tc->str, tc->flag, exp, act);
+		*ret = 1;
+		return (argv);
+	}
+
+	for (i = 1; i < argc && tc->argv[i] != NULL && argv[i] != NULL; i++) {
+		if (!strcmp(tc->argv[i], argv[i]))
+			continue;
+		printf(
+		    "ERROR: Parsing string <%s> with flags %x, "
+		    "expected <%s> for argv[%d] got <%s>.\n",
+		    tc->str, tc->flag, tc->argv[i], i, argv[i]);
+		*ret = 1;
+		return (argv);
+	}
+
+	if (tc->argv[i] != NULL || argv[i] != NULL) {
+		act = i < argc ? "less" : "more";
+		printf(
+		    "ERROR: Parsing string <%s> with flags %x, "
+		    "got %s arguments (%d) than expected.\n",
+		    tc->str, tc->flag, act, argc);
+		*ret = 1;
+		return (argv);
+	}
+
+	exp = tc->argv[0] == NULL ? "PASS" : "FAIL";
+	printf("%s: <%s> with flags %x as expected.\n", exp, tc->str, tc->flag);
+	return (argv);
+}
+
+int
+main(int argc, char **argv)
+{
+	const struct test_case **tc;
+	int ret = 0;
+
+	(void)argc;
+	(void)argv;
+
+	for (tc = tests; ret == 0 && *tc != NULL; tc++) {
+		argv = test_run(*tc, &ret);
+		VAV_Free(argv);
+	}
+
+	return (0);
+}
+#endif /* TEST_DRIVER */


More information about the varnish-commit mailing list