[master] 5a08d4cf7 vtest: Implement logexpect alternatives
Nils Goroll
nils.goroll at uplex.de
Tue Jan 12 22:11:12 UTC 2021
commit 5a08d4cf7881ea29e4723be7fbd48c8bd5cf970b
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Tue Jan 12 20:50:36 2021 +0100
vtest: Implement logexpect alternatives
This was another great idea by Dridi, thank you!
We see cases in VSL where the order of some events can not be (is hard
to) fix. For these cases, we add "all of these have to match, but we do
not care about the order" semantics through "?" in the skip column of
"expect" lines.
Example:
expect 0 = Debug 1
expect ? = Debug a
expect ? = Debug b
expect ? = Debug c
expect 0 = Debug 2
After a line has matched "1", lines matching a, b or c in any order must
follow and then a line matching "2".
In the log, an "alt" line is emitted whenever an alternative expect is
evaluated.
When an alternative matches, matching will continue with the same
"expect" as before.
Implementation:
The skip_max field of (struct logexp_test) was already used for LE_ANY
if not a non-negative integer.
We add LE_ALT and LE_SEEN. The former denotes an expect with
alternatives (that is, the instruction to look for alternatives after
this expect) and the latter denotes an LE_ALT that has been matched.
Obviously, LE_SEEN is internal and can not result from the logexpect
configuration.
When a match on an LE_ALT fails, we do not advance le->test, but rather
look forward in the expect list for any other altnertives and try them
until we either have a match or run out of alternatives.
diff --git a/bin/varnishtest/vtc_logexp.c b/bin/varnishtest/vtc_logexp.c
index f0d14b086..320bfe599 100644
--- a/bin/varnishtest/vtc_logexp.c
+++ b/bin/varnishtest/vtc_logexp.c
@@ -128,6 +128,8 @@
#define LE_ANY (-1)
#define LE_LAST (-2)
+#define LE_ALT (-3)
+#define LE_SEEN (-4)
struct logexp_test {
unsigned magic;
@@ -141,6 +143,8 @@ struct logexp_test {
int skip_max;
};
+VTAILQ_HEAD(tests_head,logexp_test);
+
struct logexp {
unsigned magic;
#define LOGEXP_MAGIC 0xE81D9F1B
@@ -150,7 +154,7 @@ struct logexp {
char *vname;
struct vtclog *vl;
char run;
- VTAILQ_HEAD(,logexp_test) tests;
+ struct tests_head tests;
struct logexp_test *test;
int skip_cnt;
@@ -248,19 +252,57 @@ logexp_new(const char *name, const char *varg)
return (le);
}
+static void
+logexp_clean(const struct tests_head *head)
+{
+ struct logexp_test *test;
+
+ VTAILQ_FOREACH(test, head, list)
+ if (test->skip_max == LE_SEEN)
+ test->skip_max = LE_ALT;
+}
+
+static struct logexp_test *
+logexp_alt(struct logexp_test *test)
+{
+ assert(test->skip_max == LE_ALT);
+
+ do
+ test = VTAILQ_NEXT(test, list);
+ while (test != NULL && test->skip_max == LE_SEEN);
+
+ if (test == NULL || test->skip_max != LE_ALT)
+ return (NULL);
+
+ return (test);
+}
+
static void
logexp_next(struct logexp *le)
{
CHECK_OBJ_NOTNULL(le, LOGEXP_MAGIC);
- if (le->test) {
+ if (le->test && le->test->skip_max == LE_ALT) {
+ /*
+ * if an alternative was not seen, continue at this expection
+ * with the next vsl
+ */
+ (void)0;
+ } else if (le->test) {
CHECK_OBJ_NOTNULL(le->test, LOGEXP_TEST_MAGIC);
le->test = VTAILQ_NEXT(le->test, list);
- } else
+ } else {
+ logexp_clean(&le->tests);
le->test = VTAILQ_FIRST(&le->tests);
+ }
+
+ if (le->test == NULL)
+ return;
- CHECK_OBJ_ORNULL(le->test, LOGEXP_TEST_MAGIC);
- if (le->test)
+ CHECK_OBJ(le->test, LOGEXP_TEST_MAGIC);
+ if (le->test->skip_max == LE_SEEN)
+ logexp_next(le);
+ else
vtc_log(le->vl, 3, "expecting| %s", VSB_data(le->test->str));
}
@@ -275,10 +317,11 @@ logexp_match(const struct logexp *le, struct logexp_test *test,
const char *data, int vxid, int tag, int type, int len)
{
const char *legend;
- int ok = 1, skip = 0;
+ int ok = 1, skip = 0, alt = 0;
AN(le);
AN(test);
+ assert(test->skip_max != LE_SEEN);
if (test->vxid == LE_LAST) {
if (le->vxid_last != vxid)
@@ -301,7 +344,10 @@ logexp_match(const struct logexp *le, struct logexp_test *test,
len, 0, 0, NULL, 0, NULL))
ok = 0;
- if (!ok && (test->skip_max == LE_ANY ||
+ if (test->skip_max == LE_ALT)
+ alt = 1;
+
+ if (!ok && !alt && (test->skip_max == LE_ANY ||
test->skip_max > le->skip_cnt))
skip = 1;
@@ -309,7 +355,7 @@ logexp_match(const struct logexp *le, struct logexp_test *test,
legend = "match";
else if (skip && le->m_arg)
legend = "miss";
- else if (skip)
+ else if (skip || alt)
legend = NULL;
else
legend = "err";
@@ -319,8 +365,18 @@ logexp_match(const struct logexp *le, struct logexp_test *test,
legend, vxid, VSL_tags[tag], type, len,
data);
- if (ok)
+ if (ok) {
+ if (alt)
+ test->skip_max = LE_SEEN;
return (LEM_OK);
+ }
+ if (alt) {
+ test = logexp_alt(test);
+ if (test == NULL)
+ return (LEM_FAIL);
+ vtc_log(le->vl, 3, "alt | %s", VSB_data(test->str));
+ return (logexp_match(le, test, data, vxid, tag, type, len));
+ }
if (skip)
return (LEM_SKIP);
return (LEM_FAIL);
@@ -485,6 +541,8 @@ cmd_logexp_expect(CMD_ARGS)
if (!strcmp(av[1], "*"))
skip_max = LE_ANY;
+ else if (!strcmp(av[1], "?"))
+ skip_max = LE_ALT;
else {
skip_max = (int)strtol(av[1], &end, 10);
if (*end != '\0' || skip_max < 0)
More information about the varnish-commit
mailing list