Commit 4aaec2ff authored by Geoff Simmons's avatar Geoff Simmons

Add the .check_call() method.

parent d6d30486
......@@ -1072,6 +1072,21 @@ SUB xset.subroutine(INT n, STRING element, ENUM select)
XXX ...
.. _xset.check_call():
BOOL xset.check_call(INT n, STRING element, ENUM select)
--------------------------------------------------------
::
BOOL xset.check_call(
INT n=0,
STRING element=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} select=UNIQUE
)
XXX ...
.. _selector.version():
STRING version()
......
......@@ -31,11 +31,11 @@
static unsigned
select(VRT_CTX, const struct match_data * const restrict match,
const char * const restrict obj, VCL_ENUM const restrict selects,
const char * const restrict method)
const char * const restrict method, int fail)
{
if (selects == VENUM(EXACT)) {
if (match->exact == UINT_MAX)
VFAIL(ctx, "%s.%s(select=EXACT): "
VFAIL_OR_NOTICE(ctx, fail, "%s.%s(select=EXACT): "
"no element matched exactly", obj, method);
return match->exact;
}
......@@ -45,8 +45,9 @@ select(VRT_CTX, const struct match_data * const restrict match,
switch (selects[0]) {
case 'U':
assert(selects == VENUM(UNIQUE));
VFAIL(ctx, "%s.%s(select=UNIQUE): %d elements were matched",
obj, method, match->n);
VFAIL_OR_NOTICE(ctx, fail,
"%s.%s(select=UNIQUE): %d elements were matched",
obj, method, match->n);
return (UINT_MAX);
case 'L':
if (selects == VENUM(LAST))
......@@ -81,7 +82,7 @@ vmod_set_which(VRT_CTX, struct vmod_selector_set *set, VCL_ENUM selects,
return (UINT_MAX);
}
match = get_existing_match_data(ctx, set, "which");
match = get_existing_match_data(ctx, set, "which", 1);
if (element != NULL) {
CHECK_OBJ_NOTNULL(match, MATCH_DATA_MAGIC);
assert(match->n == 1);
......@@ -89,35 +90,38 @@ vmod_set_which(VRT_CTX, struct vmod_selector_set *set, VCL_ENUM selects,
}
if (match == NULL || match->n == 0)
return (0);
return (select(ctx, match, set->vcl_name, selects, "which") + 1);
return (select(ctx, match, set->vcl_name, selects, "which", 1) + 1);
}
static unsigned
get_idx(VRT_CTX, VCL_INT n, const struct vmod_selector_set * const restrict set,
const char * const restrict method, VCL_STRING const restrict element,
VCL_ENUM const restrict selects)
VCL_ENUM const restrict selects, int fail)
{
struct match_data *match;
if (n > 0) {
if (n > set->nmembers) {
VFAIL(ctx, "%s.%s(%ld): set has %d elements",
set->vcl_name, method, n, set->nmembers);
VFAIL_OR_NOTICE(ctx, fail,
"%s.%s(%ld): set has %d elements",
set->vcl_name, method, n,
set->nmembers);
return (UINT_MAX);
}
return (n - 1);
}
if (element != NULL)
if (!vmod_set_match(ctx, TRUST_ME(set), element)) {
VFAIL(ctx, "%s.%s(element=\"%s\"): no such element",
set->vcl_name, method, element);
VFAIL_OR_NOTICE(ctx, fail,
"%s.%s(element=\"%s\"): no such element",
set->vcl_name, method, element);
return (UINT_MAX);
}
match = get_existing_match_data(ctx, set, method);
match = get_existing_match_data(ctx, set, method, fail);
if (match == NULL || match->n == 0)
return (UINT_MAX);
return (select(ctx, match, set->vcl_name, selects, method));
return (select(ctx, match, set->vcl_name, selects, method, fail));
}
VCL_STRING
......@@ -129,7 +133,7 @@ vmod_set_element(VRT_CTX, struct vmod_selector_set *set, VCL_INT n,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "element", NULL, selects);
idx = get_idx(ctx, n, set, "element", NULL, selects, 1);
if (idx == UINT_MAX)
return (NULL);
return (set->members[idx]);
......@@ -139,11 +143,12 @@ static inline int
check_added(VRT_CTX, const struct vmod_selector_set * const restrict set,
unsigned idx, enum bitmap_e bitmap,
const char * const restrict method,
const char * const restrict type)
const char * const restrict type, int fail)
{
if (!is_added(set, idx, bitmap)) {
VFAIL(ctx, "%s.%s(): %s not added for element %u",
set->vcl_name, method, type, idx + 1);
VFAIL_OR_NOTICE(ctx, fail,
"%s.%s(): %s not added for element %u",
set->vcl_name, method, type, idx + 1);
return (0);
}
return (1);
......@@ -159,10 +164,10 @@ vmod_set_backend(VRT_CTX, struct vmod_selector_set *set, VCL_INT n,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "backend", element, selects);
idx = get_idx(ctx, n, set, "backend", element, selects, 1);
if (idx == UINT_MAX)
return (NULL);
if (!check_added(ctx, set, idx, BACKEND, "backend", "backend"))
if (!check_added(ctx, set, idx, BACKEND, "backend", "backend", 1))
return (NULL);
b = set->table[idx]->backend;
......@@ -180,10 +185,10 @@ vmod_set_string(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "string", element, selects);
idx = get_idx(ctx, n, set, "string", element, selects, 1);
if (idx == UINT_MAX)
return (NULL);
if (!check_added(ctx, set, idx, STRING, "string", "string"))
if (!check_added(ctx, set, idx, STRING, "string", "string", 1))
return (NULL);
s = set->table[idx]->string;
......@@ -200,10 +205,10 @@ vmod_set_integer(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "integer", element, selects);
idx = get_idx(ctx, n, set, "integer", element, selects, 1);
if (idx == UINT_MAX)
return (0);
if (!check_added(ctx, set, idx, INTEGER, "integer", "integer"))
if (!check_added(ctx, set, idx, INTEGER, "integer", "integer", 1))
return (0);
return (set->table[idx]->integer);
......@@ -220,10 +225,10 @@ get_re(VRT_CTX, const struct vmod_selector_set * const restrict set,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, method, element, selects);
idx = get_idx(ctx, n, set, method, element, selects, 1);
if (idx == UINT_MAX)
return (NULL);
if (!check_added(ctx, set, idx, REGEX, method, "regex"))
if (!check_added(ctx, set, idx, REGEX, method, "regex", 1))
return (NULL);
re = set->table[idx]->re;
......@@ -265,10 +270,10 @@ vmod_set_bool(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT n,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "bool", element, selects);
idx = get_idx(ctx, n, set, "bool", element, selects, 1);
if (idx == UINT_MAX)
return (0);
if (!check_added(ctx, set, idx, BOOLEAN, "bool", "boolean"))
if (!check_added(ctx, set, idx, BOOLEAN, "bool", "boolean", 1))
return (0);
return (set->table[idx]->bool);
......@@ -283,11 +288,34 @@ vmod_set_subroutine(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT n,
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "subroutine", element, selects);
idx = get_idx(ctx, n, set, "subroutine", element, selects, 1);
if (idx == UINT_MAX)
return (NULL);
if (!check_added(ctx, set, idx, SUB, "subroutine", "subroutine"))
if (!check_added(ctx, set, idx, SUB, "subroutine", "subroutine", 1))
return (NULL);
return (set->table[idx]->sub);
}
VCL_BOOL
vmod_set_check_call(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT n,
VCL_STRING element, VCL_ENUM selects)
{
unsigned idx;
VCL_STRING err;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "check_call", element, selects, 0);
if (idx == UINT_MAX)
return (0);
if (!check_added(ctx, set, idx, SUB, "check_call", "subroutine", 0))
return (0);
if ((err = VRT_check_call(ctx, set->table[idx]->sub)) != NULL) {
VNOTICE(ctx, "%s", err);
return (0);
}
return (1);
}
......@@ -183,7 +183,7 @@ vmod_set_hasprefix(VRT_CTX, struct vmod_selector_set *set, VCL_STRING subject)
struct match_data *
get_existing_match_data(VRT_CTX,
const struct vmod_selector_set * const restrict set,
const char * const restrict method)
const char * const restrict method, int fail)
{
struct vmod_priv *task;
struct match_data *match;
......@@ -191,8 +191,8 @@ get_existing_match_data(VRT_CTX,
task = VRT_priv_task(ctx, set);
AN(task);
if (task->priv == NULL) {
VFAIL(ctx, "%s.%s() called without prior match", set->vcl_name,
method);
VFAIL_OR_NOTICE(ctx, fail, "%s.%s() called without prior match",
set->vcl_name, method);
return (NULL);
}
WS_Assert_Allocated(ctx->ws, task->priv, sizeof(*match));
......@@ -208,7 +208,7 @@ vmod_set_nmatches(VRT_CTX, struct vmod_selector_set *set)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
match = get_existing_match_data(ctx, set, "nmatches");
match = get_existing_match_data(ctx, set, "nmatches", 1);
if (match == NULL)
return (0);
return (match->n);
......@@ -229,7 +229,7 @@ vmod_set_matched(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT idx,
return (0);
}
match = get_existing_match_data(ctx, set, "matched");
match = get_existing_match_data(ctx, set, "matched", 1);
if (match == NULL || match->n == 0)
return (0);
......
# looks like -*- vcl -*-
varnishtest "call() method"
varnishtest ".subroutine() and .check_call() methods"
varnish v1 -vcl {
import ${vmod_selector};
......@@ -65,6 +65,12 @@ varnish v1 -vcl {
}
sub vcl_synth {
set resp.http.Check-1 = s.check_call(1);
set resp.http.Check-2 = s.check_call(2);
set resp.http.Check-3 = s.check_call(3);
set resp.http.Check-4 = s.check_call(4);
set resp.http.Check-5 = s.check_call(5);
set resp.http.X = "N";
call s.subroutine(1);
call s.subroutine(2);
......@@ -81,8 +87,25 @@ varnish v1 -vcl {
call s.subroutine(select=LAST);
call s.subroutine(select=SHORTEST);
call s.subroutine(select=LONGEST);
set resp.http.Check-Noarg = s.check_call();
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
}
set resp.http.Check-Foo = s.check_call(element="foo");
set resp.http.Check-Bar = s.check_call(element="bar");
set resp.http.Check-Baz = s.check_call(element="baz");
set resp.http.Check-Quux = s.check_call(element="quux");
set resp.http.Check-Foobar = s.check_call(element="foobar");
set resp.http.X = "E";
call s.subroutine(element="foo");
call s.subroutine(element="bar");
......@@ -90,6 +113,8 @@ varnish v1 -vcl {
call s.subroutine(element="quux");
call s.subroutine(element="foobar");
if (req.http.Element) {
set resp.http.Check-Element
= s.check_call(element=req.http.Element);
call s.subroutine(element=req.http.Element);
}
......@@ -101,6 +126,18 @@ client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Check-1 == true
expect resp.http.Check-2 == true
expect resp.http.Check-3 == true
expect resp.http.Check-4 == true
expect resp.http.Check-5 == true
expect resp.http.Check-Foo == true
expect resp.http.Check-Bar == true
expect resp.http.Check-Baz == true
expect resp.http.Check-Quux == true
expect resp.http.Check-Foobar == true
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
expect resp.http.Baz == "NE"
......@@ -110,6 +147,14 @@ client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "NSSSSSSSE"
expect resp.http.Bar == "NE"
expect resp.http.Baz == "NE"
......@@ -119,6 +164,14 @@ client c1 {
txreq -hdr "Word: bar"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NSSSSSSSE"
expect resp.http.Baz == "NE"
......@@ -127,6 +180,14 @@ client c1 {
txreq -hdr "Word: baz"
rxresp
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.status == 200
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
......@@ -136,6 +197,14 @@ client c1 {
txreq -hdr "Word: quux"
rxresp
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.status == 200
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
......@@ -146,6 +215,14 @@ client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "NE"
expect resp.http.Bar == "NE"
expect resp.http.Baz == "NE"
......@@ -162,6 +239,12 @@ logexpect l1 -v v1 -d 1 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.match\(\): subject string is NULL$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.match\(\): subject string is NULL$}
expect * = Notice {^vmod_selector: s\.check_call\(element="oof"\): no such element$}
expect 0 = RespHeader {^Check-Element: false$}
expect * = End
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
......@@ -178,23 +261,23 @@ varnish v1 -vcl {
backend b None;
sub foo {
set resp.http.Called = "foo";
set req.http.Called = "foo";
}
sub bar {
set resp.http.Called = "bar";
set req.http.Called = "bar";
}
sub baz {
set resp.http.Called = "baz";
set req.http.Called = "baz";
}
sub quux {
set resp.http.Called = "quux";
set req.http.Called = "quux";
}
sub foobar {
set resp.http.Called = "foobar";
set req.http.Called = "foobar";
}
sub vcl_init {
......@@ -207,9 +290,18 @@ varnish v1 -vcl {
}
sub vcl_recv {
set req.http.Check-Call
= s.check_call(std.integer(req.http.Int));
call s.subroutine(std.integer(req.http.Int));
return (synth(200));
}
sub vcl_synth {
if (req.http.Called) {
set resp.http.Called = req.http.Called;
}
return (deliver);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
......@@ -229,6 +321,23 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(\) called without prior match$}
expect 0 = ReqHeader {^Check-Call: false$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(\) called without prior match$}
expect 0 = ReqHeader {^Check-Call: false$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(6\): set has 5 elements$}
expect 0 = ReqHeader {^Check-Call: false$}
expect * = End
} -start
client c1 {
txreq -hdr "Int: -1"
rxresp
......@@ -257,6 +366,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_selector};
......@@ -289,6 +399,17 @@ varnish v1 -vcl {
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Check-Noarg = s.check_call();
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
call s.subroutine();
call s.subroutine(select=UNIQUE);
call s.subroutine(select=EXACT);
......@@ -299,6 +420,17 @@ varnish v1 -vcl {
}
if (req.http.Element) {
call s.subroutine(element=req.http.Element);
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
call s.subroutine(select=UNIQUE);
call s.subroutine(select=EXACT);
call s.subroutine(select=FIRST);
......@@ -315,12 +447,25 @@ client c1 {
rxresp
expect resp.status == 200
expect resp.http.Foo == "XXXXXXX"
expect resp.http.Check-Noarg == true
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Called == <undef>
txreq -hdr "Element: foo"
rxresp
expect resp.status == 200
expect resp.http.Foo == "XXXXXXX"
expect resp.http.Check-Unique == true
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Called == <undef>
} -run
......@@ -380,6 +525,17 @@ varnish v1 -vcl {
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Check-Noarg = s.check_call();
set resp.http.Check-Unique
= s.check_call(select=UNIQUE);
set resp.http.Check-Exact = s.check_call(select=EXACT);
set resp.http.Check-First = s.check_call(select=FIRST);
set resp.http.Check-Last = s.check_call(select=LAST);
set resp.http.Check-Shortest
= s.check_call(select=SHORTEST);
set resp.http.Check-Longest
= s.check_call(select=LONGEST);
set resp.http.X = "E";
call s.subroutine(select=EXACT);
set resp.http.X = "F";
......@@ -395,10 +551,34 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 3 elements were matched$}
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 3 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 4 elements were matched$}
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 4 elements were matched$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == false
expect resp.http.Check-Unique == false
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "LaS"
expect resp.http.Foobar == "EFLo"
expect resp.http.Foobarbaz == <undef>
......@@ -407,6 +587,13 @@ client c1 {
txreq -hdr "Word: foobarbaz"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == false
expect resp.http.Check-Unique == false
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "LaS"
expect resp.http.Foobar == <undef>
expect resp.http.Foobarbaz == "EFLo"
......@@ -415,12 +602,21 @@ client c1 {
txreq -hdr "Word: foobarbazquux"
rxresp
expect resp.status == 200
expect resp.http.Check-Noarg == false
expect resp.http.Check-Unique == false
expect resp.http.Check-Exact == true
expect resp.http.Check-First == true
expect resp.http.Check-Last == true
expect resp.http.Check-Longest == true
expect resp.http.Check-Shortest == true
expect resp.http.Foo == "LaS"
expect resp.http.Foobar == <undef>
expect resp.http.Foobarbaz == <undef>
expect resp.http.Foobarbazquux == "EFLo"
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b None;
......@@ -451,6 +647,8 @@ varnish v1 -vcl {
sub vcl_recv {
if (s.hasprefix(req.http.Word)) {
set req.http.Check-Unique = s.check_call(select=UNIQUE);
set req.http.Check-Exact = s.check_call(select=EXACT);
call s.subroutine(select=EXACT);
call s.subroutine(select=UNIQUE);
}
......@@ -471,6 +669,21 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect 0 = ReqHeader {^Check-Unique: false$}
expect 0 = ReqHeader {^Check-Exact: true$}
expect * = End
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(select=UNIQUE\): 2 elements were matched$}
expect 0 = ReqHeader {^Check-Unique: false$}
expect 0 = Notice {^vmod_selector: s\.check_call\(select=EXACT\): no element matched exactly$}
expect 0 = ReqHeader {^Check-Exact: false$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar"
rxresp
......@@ -488,6 +701,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_selector};
......@@ -505,12 +719,14 @@ varnish v1 -vcl {
sub vcl_recv {
if (s.match(req.http.Word)) {
set req.http.Check = s.check_call();
call s.subroutine();
}
return (synth(200));
}
sub vcl_synth {
set resp.http.Check = req.http.Check;
set resp.http.Foo = req.http.Foo;
return (deliver);
}
......@@ -523,10 +739,18 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: s\.check_call\(\): subroutine not added for element 2$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Check == "true"
expect resp.http.Foo == "called"
txreq -hdr "Word: bar"
......@@ -537,6 +761,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -errvcl {Symbol not found: 'foo'} {
import ${vmod_selector};
......@@ -562,6 +787,7 @@ varnish v1 -vcl {
}
sub vcl_recv {
set req.http.Check = s.check_call(element="foo");
call s.subroutine(element="foo");
return (synth(200));
}
......@@ -574,6 +800,13 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: Dynamic call to "sub foo\{\}" not allowed from here$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq
rxresp
......@@ -583,6 +816,7 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
varnish v1 -vcl {
import ${vmod_selector};
......@@ -598,6 +832,7 @@ varnish v1 -vcl {
}
sub bar {
set req.http.Check = s.check_call(element="foo");
call s.subroutine(element="foo");
}
......@@ -614,6 +849,13 @@ logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * = End
} -start
logexpect l2 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = Notice {^vmod_selector: Recursive dynamic call to "sub foo\{\}"$}
expect 0 = ReqHeader {^Check: false$}
expect * = End
} -start
client c1 {
txreq
rxresp
......@@ -623,3 +865,4 @@ client c1 {
} -run
logexpect l1 -wait
logexpect l2 -wait
......@@ -45,6 +45,13 @@
#define VNOTICE(ctx, fmt, ...) \
VSLb((ctx)->vsl, SLT_Notice, "vmod_selector: " fmt, __VA_ARGS__)
#define VFAIL_OR_NOTICE(ctx, fail, fmt, ...) do { \
if (fail) \
VFAIL((ctx), fmt, __VA_ARGS__); \
else \
VNOTICE((ctx), fmt, __VA_ARGS__); \
} while(0)
struct entry {
unsigned magic;
#define VMOD_SELECTOR_ENTRY_MAGIC 0x733dbe63
......@@ -101,4 +108,4 @@ is_added(const struct vmod_selector_set *set, unsigned idx,
struct match_data *
get_existing_match_data(const struct vrt_ctx *ctx,
const struct vmod_selector_set * const restrict set,
const char * const restrict method);
const char * const restrict method, int fail);
......@@ -937,6 +937,12 @@ $Method SUB .subroutine(INT n=0, STRING element=0,
XXX ...
$Method BOOL .check_call(INT n=0, STRING element=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST}
select=UNIQUE)
XXX ...
$Function STRING version()
Return the version string for this VMOD.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment