[master] 0a2c6dad4 vtc: varnish vNAME -expect PATTERN OP PATTERN

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Wed Dec 2 10:43:10 UTC 2020


commit 0a2c6dad4db82008e8bca67f8132589725c8a3e6
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Mon Nov 30 16:06:38 2020 +0100

    vtc: varnish vNAME -expect PATTERN OP PATTERN
    
    Make it possible to compare VSCs, to create a synchronization point
    based on internal events (especially with custom VSCs).
    
    For example:
    
        # block until baz catches up
        varnish v1 -expect FOO.bar == FOO.baz
    
    This is still subject to roughly 5s before timing out.

diff --git a/bin/varnishtest/tests/b00052.vtc b/bin/varnishtest/tests/b00052.vtc
index 23cfcf5de..90cba6988 100644
--- a/bin/varnishtest/tests/b00052.vtc
+++ b/bin/varnishtest/tests/b00052.vtc
@@ -1,23 +1,27 @@
 varnishtest "The cache_hit_grace counter"
 
 server s1 {
-	# normal fetch
 	rxreq
 	expect req.url == "/1"
+	expect req.http.bgfetch == false
 	txresp -hdr "Age: 1" -hdr "Cache-Control: max-age=2" -body "1"
 
-	# background fetch:
 	rxreq
 	expect req.url == "/1"
+	expect req.http.bgfetch == true
 	txresp -body "2"
 
-	# normal fetch
 	rxreq
 	expect req.url == "/2"
+	expect req.http.bgfetch == false
 	txresp
 } -start
 
-varnish v1 -vcl+backend { } -start
+varnish v1 -vcl+backend {
+	sub vcl_backend_fetch {
+		set bereq.http.bgfetch = bereq.is_bgfetch;
+	}
+} -start
 
 client c1 {
 	txreq -url "/1"
@@ -35,6 +39,8 @@ client c2 {
 	expect resp.body == "1"
 } -run
 
+varnish v1 -expect cache_hit >= cache_hit_grace
+
 delay 2
 
 client c3 {
@@ -45,6 +51,8 @@ client c3 {
 	expect resp.body == "2"
 } -run
 
+varnish v1 -expect cache_hit >= cache_hit_grace
+
 # Check that counters are correct:
 
 varnish v1 -expect cache_hit == 2
diff --git a/bin/varnishtest/tests/r02946.vtc b/bin/varnishtest/tests/r02946.vtc
index ecda00483..71872679a 100644
--- a/bin/varnishtest/tests/r02946.vtc
+++ b/bin/varnishtest/tests/r02946.vtc
@@ -44,4 +44,5 @@ client c1 {
 
 delay 1
 
+varnish v1 -expect s_fetch > s_bgfetch
 varnish v1 -expect n_objectcore == 1
diff --git a/bin/varnishtest/vtc_varnish.c b/bin/varnishtest/vtc_varnish.c
index 9912da43b..d1f962919 100644
--- a/bin/varnishtest/vtc_varnish.c
+++ b/bin/varnishtest/vtc_varnish.c
@@ -910,12 +910,29 @@ varnish_vsc(const struct varnish *v, const char *arg)
  * Check statistics
  */
 
+struct stat_arg {
+	const char	*pattern;
+	uintmax_t	val;
+	unsigned	good;
+};
+
 struct stat_priv {
-	char target_pattern[256];
-	uintmax_t val;
-	const struct varnish *v;
+	struct stat_arg	lhs;
+	struct stat_arg	rhs;
 };
 
+static int
+stat_match(const char *pattern, const char *name)
+{
+
+	if (strchr(pattern, '.') == NULL) {
+		if (fnmatch("MAIN.*", name, 0))
+			return (FNM_NOMATCH);
+		name += 5;
+	}
+	return (fnmatch(pattern, name, 0));
+}
+
 static int
 do_expect_cb(void *priv, const struct VSC_point * const pt)
 {
@@ -924,13 +941,24 @@ do_expect_cb(void *priv, const struct VSC_point * const pt)
 	if (pt == NULL)
 		return (0);
 
-	if (fnmatch(sp->target_pattern, pt->name, 0))
-		return (0);
+	if (!sp->lhs.good && stat_match(sp->lhs.pattern, pt->name) == 0) {
+		AZ(strcmp(pt->ctype, "uint64_t"));
+		AN(pt->ptr);
+		sp->lhs.val = *pt->ptr;
+		sp->lhs.good = 1;
+	}
 
-	AZ(strcmp(pt->ctype, "uint64_t"));
-	AN(pt->ptr);
-	sp->val = *pt->ptr;
-	return (1);
+	if (sp->rhs.pattern == NULL) {
+		sp->rhs.good = 1;
+	} else if (!sp->rhs.good &&
+	    stat_match(sp->rhs.pattern, pt->name) == 0) {
+		AZ(strcmp(pt->ctype, "uint64_t"));
+		AN(pt->ptr);
+		sp->rhs.val = *pt->ptr;
+		sp->rhs.good = 1;
+	}
+
+	return (sp->lhs.good && sp->rhs.good);
 }
 
 /**********************************************************************
@@ -939,55 +967,49 @@ do_expect_cb(void *priv, const struct VSC_point * const pt)
 static void
 varnish_expect(const struct varnish *v, char * const *av)
 {
-	uint64_t ref;
-	int good;
-	char *r;
-	char *p;
-	int i, not = 0;
 	struct stat_priv sp;
-
-	r = av[0];
-	if (r[0] == '!') {
-		not = 1;
-		r++;
+	int good, i, not;
+	uintmax_t u;
+	char *l, *p;
+
+	ZERO_OBJ(&sp, sizeof sp);
+	l = av[0];
+	not = (*l == '!');
+	if (not) {
+		l++;
 		AZ(av[1]);
 	} else {
 		AN(av[1]);
 		AN(av[2]);
-	}
-	p = strrchr(r, '.');
-	if (p == NULL) {
-		bprintf(sp.target_pattern, "MAIN.%s", r);
-	} else {
-		bprintf(sp.target_pattern, "%s", r);
+		u = strtoumax(av[2], &p, 0);
+		if (u != UINTMAX_MAX && *p == '\0')
+			sp.rhs.val = u;
+		else
+			sp.rhs.pattern = av[2];
 	}
 
-	sp.val = 0;
-	sp.v = v;
-	ref = 0;
-	good = 0;
+	sp.lhs.pattern = l;
+
 	for (i = 0; i < 50; i++, (void)usleep(100000)) {
 		(void)VSM_Status(v->vsm_vsc);
+		sp.lhs.good = sp.rhs.good = 0;
 		good = VSC_Iter(v->vsc, v->vsm_vsc, do_expect_cb, &sp);
-		if (!good) {
+		if (!good)
 			good = -2;
+		if (good < 0)
 			continue;
-		}
 
 		if (not)
-			vtc_fatal(v->vl, "Found (not expected): %s", av[0]+1);
-
-		good = 0;
-		ref = strtoumax(av[2], &p, 0);
-		if (ref == UINTMAX_MAX || *p)
-			vtc_fatal(v->vl, "Syntax error in number (%s)", av[2]);
-		if      (!strcmp(av[1], "==")) { if (sp.val == ref) good = 1; }
-		else if (!strcmp(av[1], "!=")) { if (sp.val != ref) good = 1; }
-		else if (!strcmp(av[1], ">"))  { if (sp.val > ref)  good = 1; }
-		else if (!strcmp(av[1], "<"))  { if (sp.val < ref)  good = 1; }
-		else if (!strcmp(av[1], ">=")) { if (sp.val >= ref) good = 1; }
-		else if (!strcmp(av[1], "<=")) { if (sp.val <= ref) good = 1; }
-		else
+			vtc_fatal(v->vl, "Found (not expected): %s", l);
+
+		good = -1;
+		if (!strcmp(av[1], "==")) good = (sp.lhs.val == sp.rhs.val);
+		if (!strcmp(av[1], "!=")) good = (sp.lhs.val != sp.rhs.val);
+		if (!strcmp(av[1], ">" )) good = (sp.lhs.val >  sp.rhs.val);
+		if (!strcmp(av[1], "<" )) good = (sp.lhs.val <  sp.rhs.val);
+		if (!strcmp(av[1], ">=")) good = (sp.lhs.val >= sp.rhs.val);
+		if (!strcmp(av[1], "<=")) good = (sp.lhs.val <= sp.rhs.val);
+		if (good == -1)
 			vtc_fatal(v->vl, "comparison %s unknown", av[1]);
 		if (good)
 			break;
@@ -997,19 +1019,19 @@ varnish_expect(const struct varnish *v, char * const *av)
 	}
 	if (good == -2) {
 		if (not) {
-			vtc_log(v->vl, 2, "not found (as expected): %s",
-			    av[0] + 1);
+			vtc_log(v->vl, 2, "not found (as expected): %s", l);
 			return;
 		}
-		vtc_fatal(v->vl, "stats field %s unknown", av[0]);
+		vtc_fatal(v->vl, "stats field %s unknown",
+		    sp.lhs.good ? sp.rhs.pattern : sp.lhs.pattern);
 	}
 
 	if (good == 1) {
-		vtc_log(v->vl, 2, "as expected: %s (%ju) %s %s",
-		    av[0], sp.val, av[1], av[2]);
+		vtc_log(v->vl, 2, "as expected: %s (%ju) %s %s (%ju)",
+		    av[0], sp.lhs.val, av[1], av[2], sp.rhs.val);
 	} else {
 		vtc_fatal(v->vl, "Not true: %s (%ju) %s %s (%ju)",
-		    av[0], (uintmax_t)sp.val, av[1], av[2], (uintmax_t)ref);
+		    av[0], sp.lhs.val, av[1], av[2], sp.rhs.val);
 	}
 }
 
@@ -1091,11 +1113,14 @@ varnish_expect(const struct varnish *v, char * const *av)
  *         Once Varnish is stopped, clean everything after it. This is only used
  *         in very few tests and you should never need it.
  *
+ * \-expectexit NUMBER
+ *         Expect varnishd to exit(3) with this value
+ *
  * Once Varnish is started, you can talk to it (as you would through
  * ``varnishadm``) with these additional switches::
  *
  *         varnish vNAME [-cli STRING] [-cliok STRING] [-clierr STRING]
- *                       [-clijson STRING] [-expect STRING OP NUMBER]
+ *                       [-clijson STRING]
  *
  * \-cli STRING|-cliok STRING|-clierr STATUS STRING|-cliexpect REGEXP STRING
  *         All four of these will send STRING to the CLI, the only difference
@@ -1107,14 +1132,22 @@ varnish_expect(const struct varnish *v, char * const *av)
  *	   Send STRING to the CLI, expect success (CLIS_OK/200) and check
  *	   that the response is parsable JSON.
  *
- * \-expect PATTERN OP NUMBER
+ * It is also possible to interact with its shared memory (as you would
+ * through tools like ``varnishstat``) with additional switches:
+ *
+ * \-expect \!PATTERN|PATTERN OP NUMBER|PATTERN OP PATTERN
  *         Look into the VSM and make sure the first VSC counter identified by
  *         PATTERN has a correct value. OP can be ==, >, >=, <, <=. For
  *         example::
  *
  *                 varnish v1 -expect SM?.s1.g_space > 1000000
- * \-expectexit NUMBER
- *	   Expect varnishd to exit(3) with this value
+ *                 varnish v1 -expect cache_hit >= cache_hit_grace
+ *
+ *         In the \! form the test fails if a counter matches PATTERN.
+ *
+ *         The ``MAIN.`` namespace can be omitted from PATTERN.
+ *
+ *         The test takes up to 5 seconds before timing out.
  *
  * \-vsc PATTERN
  *         Dump VSC counters matching PATTERN.


More information about the varnish-commit mailing list