Commit 11ac404d authored by Geoff Simmons's avatar Geoff Simmons

Extend .matched(), and invoke VCL failure for more error conditions.

VCL failure is invoked if:
- no entries were added to a set
- a set was not compiled
- .compile() is called in a VCL sub other than vcl_init
- a numeric index is out of range (larger than nmembers)
- the conditions for UNIQUE or EXACT fail
- associated data to be retrieved (string, backend etc) was not added

If .match() or .hasprefix() are called with a NULL subject, it is
logged using tag Notice, but is not an error (return value is false).
This is because it may or may not be intentional to attempt a match
against an unset header.

The .matched() method now may have a select argument, and works
similarly to other methods with the f(INT n, ENUM select) signature,
except that it returns false when the select condition fails, but
does not invoke VCL failure. This makes it possible to check if
UNIQUE or EXACT may be used, and avoid VCL failure if desired.
parent 6fb722b6
......@@ -36,7 +36,7 @@ SYNOPSIS
# Match properties
INT <obj>.nmatches()
BOOL <obj>.matched(INT)
BOOL <obj>.matched([INT n] [, ENUM select])
INT <obj>.which([ENUM select])
# Retrieving objects after match
......@@ -506,8 +506,15 @@ Example::
.. _xset.matched():
BOOL xset.matched(INT)
----------------------
BOOL xset.matched(INT n, ENUM select)
-------------------------------------
::
BOOL xset.matched(
INT n=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST} select=UNIQUE
)
After a successful ``.match()`` or ``.hasprefix()`` call for the same
set object in the same task scope, return ``true`` if the element
......
......@@ -4,6 +4,7 @@ varnishtest "backend() method"
varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b1 { .host = "${bad_ip}"; }
backend b2 { .host = "${bad_ip}"; }
......@@ -32,9 +33,9 @@ varnish v1 -vcl {
set resp.http.N-4 = s.backend(4);
set resp.http.N-5 = s.backend(5);
set resp.http.N--1 = s.backend(-1);
set resp.http.N-0 = s.backend(0);
set resp.http.N-6 = s.backend(6);
if (req.http.N) {
set resp.http.N = s.backend(std.integer(req.http.N));
}
if (s.match(req.http.Word)) {
set resp.http.Backend = s.backend();
......@@ -61,10 +62,6 @@ client c1 {
expect resp.http.N-4 == "b4"
expect resp.http.N-5 == "b5"
expect resp.http.N--1 == ""
expect resp.http.N-0 == ""
expect resp.http.N-6 == ""
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
......@@ -121,11 +118,25 @@ client c1 {
expect resp.http.Backend-Longest == "b5"
} -run
client c1 {
txreq -hdr "N: -1"
expect_close
} -run
client c1 {
txreq -hdr "N: 6"
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.backend\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.backend\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.backend\(6\): set has 5 elements$}
expect * = VCL_Error {^vmod selector failure: s\.backend\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.backend\(6\): set has 5 elements$}
expect * = VCL_return fail
expect * = End
} -run
......@@ -150,10 +161,23 @@ varnish v1 -vcl {
}
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Backend = s.backend();
if (req.http.Select == "UNIQUE" && s.hasprefix(req.http.Word)) {
set resp.http.Backend-Unique = s.backend(select=UNIQUE);
}
elsif (req.http.Select == "EXACT"
&& s.hasprefix(req.http.Word)) {
set resp.http.Backend-Exact = s.backend(select=EXACT);
}
elsif (s.hasprefix(req.http.Word)) {
if (s.nmatches() == 1) {
set resp.http.Backend = s.backend();
set resp.http.Backend-Unique
= s.backend(select=UNIQUE);
}
if (s.matched(select=EXACT)) {
set resp.http.Backend-Exact
= s.backend(select=EXACT);
}
set resp.http.Backend-First = s.backend(select=FIRST);
set resp.http.Backend-Last = s.backend(select=LAST);
set resp.http.Backend-Shortest
......@@ -165,29 +189,6 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * 1009 Begin req
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 2 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 3 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 4 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.backend\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.backend\(select=EXACT\): no element matched exactly$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
......@@ -203,8 +204,8 @@ client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Backend == ""
expect resp.http.Backend-Unique == ""
expect resp.http.Backend == <undef>
expect resp.http.Backend-Unique == <undef>
expect resp.http.Backend-Exact == "b3"
expect resp.http.Backend-First == "b3"
expect resp.http.Backend-Last == "b4"
......@@ -214,8 +215,8 @@ client c1 {
txreq -hdr "Word: foobarbaz"
rxresp
expect resp.status == 200
expect resp.http.Backend == ""
expect resp.http.Backend-Unique == ""
expect resp.http.Backend == <undef>
expect resp.http.Backend-Unique == <undef>
expect resp.http.Backend-Exact == "b2"
expect resp.http.Backend-First == "b2"
expect resp.http.Backend-Last == "b4"
......@@ -225,8 +226,8 @@ client c1 {
txreq -hdr "Word: foobarbazquux"
rxresp
expect resp.status == 200
expect resp.http.Backend == ""
expect resp.http.Backend-Unique == ""
expect resp.http.Backend == <undef>
expect resp.http.Backend-Unique == <undef>
expect resp.http.Backend-Exact == "b1"
expect resp.http.Backend-First == "b1"
expect resp.http.Backend-Last == "b4"
......@@ -236,15 +237,57 @@ client c1 {
txreq -hdr "Word: foobarb"
rxresp
expect resp.status == 200
expect resp.http.Backend == ""
expect resp.http.Backend-Unique == ""
expect resp.http.Backend-Exact == ""
expect resp.http.Backend == <undef>
expect resp.http.Backend-Unique == <undef>
expect resp.http.Backend-Exact == <undef>
expect resp.http.Backend-First == "b3"
expect resp.http.Backend-Last == "b4"
expect resp.http.Backend-Shortest == "b4"
expect resp.http.Backend-Longest == "b3"
} -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.backend\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.backend\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.backend\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.backend\(select=EXACT\): no element matched exactly$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbaz" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbazquux" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarb" -hdr "Select: EXACT"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
......@@ -272,27 +315,28 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.backend\(\): backend not added for element 2$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.Backend == "b"
txreq -hdr "Word: bar"
rxresp
expect resp.status == 200
expect resp.http.Backend == ""
txreq -hdr "Word: bazz"
rxresp
expect resp.status == 200
expect resp.http.Backend == ""
} -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.backend\(\): backend not added for element 2$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Word: bar"
expect_close
} -run
logexpect l1 -wait
......@@ -4,7 +4,7 @@ varnishtest "case insensitive matches"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new t = selector.set(case_sensitive=false);
......@@ -53,7 +53,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
# 100 random choices from /usr/share/dict/words
......@@ -783,7 +783,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set(case_sensitive=false);
......@@ -803,9 +803,13 @@ varnish v1 -vcl {
set resp.http.Match = s.hasprefix(req.http.Word);
std.timestamp("AfterMatch");
set resp.http.N = s.nmatches();
set resp.http.Which = s.which();
set resp.http.Which-Unique = s.which(select=UNIQUE);
set resp.http.Which-Exact = s.which(select=EXACT);
if (s.matched(select=UNIQUE)) {
set resp.http.Which = s.which();
set resp.http.Which-Unique = s.which(select=UNIQUE);
}
if (s.matched(select=EXACT)) {
set resp.http.Which-Exact = s.which(select=EXACT);
}
set resp.http.Which-First = s.which(select=FIRST);
set resp.http.Which-Last = s.which(select=LAST);
set resp.http.Which-Shortest = s.which(select=SHORTEST);
......@@ -842,7 +846,7 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.N == "2"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "3"
expect resp.http.Which-First == "3"
......@@ -859,7 +863,7 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.N == "3"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "2"
expect resp.http.Which-First == "2"
......@@ -876,7 +880,7 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.N == "4"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "1"
expect resp.http.Which-First == "1"
......@@ -893,9 +897,9 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.N == "0"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "0"
expect resp.http.Which-Exact == <undef>
expect resp.http.Which-First == "0"
expect resp.http.Which-Last == "0"
expect resp.http.Which-Shortest == "0"
......@@ -910,9 +914,9 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.N == "0"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "0"
expect resp.http.Which-Exact == <undef>
expect resp.http.Which-First == "0"
expect resp.http.Which-Last == "0"
expect resp.http.Which-Shortest == "0"
......@@ -927,9 +931,9 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.N == "0"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "0"
expect resp.http.Which-Exact == <undef>
expect resp.http.Which-First == "0"
expect resp.http.Which-Last == "0"
expect resp.http.Which-Shortest == "0"
......@@ -944,9 +948,9 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.N == "0"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "0"
expect resp.http.Which-Exact == <undef>
expect resp.http.Which-First == "0"
expect resp.http.Which-Last == "0"
expect resp.http.Which-Shortest == "0"
......@@ -961,7 +965,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set(case_sensitive=false);
......@@ -984,9 +988,13 @@ varnish v1 -vcl {
set resp.http.Match = s.hasprefix(req.http.Word);
std.timestamp("AfterMatch");
set resp.http.N = s.nmatches();
set resp.http.Which = s.which();
set resp.http.Which-Unique = s.which(select=UNIQUE);
set resp.http.Which-Exact = s.which(select=EXACT);
if (s.matched(select=UNIQUE)) {
set resp.http.Which = s.which();
set resp.http.Which-Unique = s.which(select=UNIQUE);
}
if (s.matched(select=EXACT)) {
set resp.http.Which-Exact = s.which(select=EXACT);
}
set resp.http.Which-First = s.which(select=FIRST);
set resp.http.Which-Last = s.which(select=LAST);
set resp.http.Which-Shortest = s.which(select=SHORTEST);
......@@ -1001,7 +1009,7 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.N == "3"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "3"
expect resp.http.Which-First == "1"
......@@ -1014,7 +1022,7 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.N == "2"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "1"
expect resp.http.Which-First == "1"
......@@ -1042,7 +1050,7 @@ client c1 {
expect resp.http.N == "1"
expect resp.http.Which == "5"
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "0"
expect resp.http.Which-Exact == <undef>
expect resp.http.Which-First == "5"
expect resp.http.Which-Last == "5"
expect resp.http.Which-Shortest == "5"
......@@ -1053,9 +1061,9 @@ client c1 {
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.N == "0"
expect resp.http.Which == "0"
expect resp.http.Which == <undef>
expect resp.http.Which-Unique == resp.http.Which
expect resp.http.Which-Exact == "0"
expect resp.http.Which-Exact == <undef>
expect resp.http.Which-First == "0"
expect resp.http.Which-Last == "0"
expect resp.http.Which-Shortest == "0"
......
......@@ -4,7 +4,8 @@ varnishtest "element() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
import std;
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -27,9 +28,9 @@ varnish v1 -vcl {
set resp.http.N-4 = s.element(4);
set resp.http.N-5 = s.element(5);
set resp.http.N--1 = s.element(-1);
set resp.http.N-0 = s.element(0);
set resp.http.N-6 = s.element(6);
if (req.http.N) {
set resp.http.N = s.element(std.integer(req.http.N));
}
if (s.match(req.http.Word)) {
set resp.http.Element = s.element();
......@@ -56,10 +57,6 @@ client c1 {
expect resp.http.N-4 == "quux"
expect resp.http.N-5 == "foobar"
expect resp.http.N--1 == ""
expect resp.http.N-0 == ""
expect resp.http.N-6 == ""
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
......@@ -116,17 +113,41 @@ client c1 {
expect resp.http.Element-Longest == "foobar"
} -run
client c1 {
txreq -hdr "N: -1"
expect_close
} -run
client c1 {
txreq -hdr "N: 0"
expect_close
} -run
client c1 {
txreq -hdr "N: 6"
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.element\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.element\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.element\(6\): set has 5 elements$}
expect * = VCL_Error {^vmod selector failure: s\.element\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.element\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.element\(6\): set has 5 elements$}
expect * = VCL_return fail
expect * = End
} -run
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -142,10 +163,23 @@ varnish v1 -vcl {
}
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Element = s.element();
if (req.http.Select == "UNIQUE" && s.hasprefix(req.http.Word)) {
set resp.http.Element-Unique = s.element(select=UNIQUE);
}
elsif (req.http.Select == "EXACT"
&& s.hasprefix(req.http.Word)) {
set resp.http.Element-Exact = s.element(select=EXACT);
}
elsif (s.hasprefix(req.http.Word)) {
if (s.nmatches() == 1) {
set resp.http.Element = s.element();
set resp.http.Element-Unique
= s.element(select=UNIQUE);
}
if (s.matched(select=EXACT)) {
set resp.http.Element-Exact
= s.element(select=EXACT);
}
set resp.http.Element-First = s.element(select=FIRST);
set resp.http.Element-Last = s.element(select=LAST);
set resp.http.Element-Shortest
......@@ -157,29 +191,6 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * 1009 Begin req
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 2 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 3 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 4 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.element\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.element\(select=EXACT\): no element matched exactly$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
......@@ -195,8 +206,8 @@ client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.Element == ""
expect resp.http.Element-Unique == ""
expect resp.http.Element == <undef>
expect resp.http.Element-Unique == <undef>
expect resp.http.Element-Exact == "foobar"
expect resp.http.Element-First == "foobar"
expect resp.http.Element-Last == "foo"
......@@ -206,8 +217,8 @@ client c1 {
txreq -hdr "Word: foobarbaz"
rxresp
expect resp.status == 200
expect resp.http.Element == ""
expect resp.http.Element-Unique == ""
expect resp.http.Element == <undef>
expect resp.http.Element-Unique == <undef>
expect resp.http.Element-Exact == "foobarbaz"
expect resp.http.Element-First == "foobarbaz"
expect resp.http.Element-Last == "foo"
......@@ -217,8 +228,8 @@ client c1 {
txreq -hdr "Word: foobarbazquux"
rxresp
expect resp.status == 200
expect resp.http.Element == ""
expect resp.http.Element-Unique == ""
expect resp.http.Element == <undef>
expect resp.http.Element-Unique == <undef>
expect resp.http.Element-Exact == "foobarbazquux"
expect resp.http.Element-First == "foobarbazquux"
expect resp.http.Element-Last == "foo"
......@@ -228,13 +239,55 @@ client c1 {
txreq -hdr "Word: foobarb"
rxresp
expect resp.status == 200
expect resp.http.Element == ""
expect resp.http.Element-Unique == ""
expect resp.http.Element-Exact == ""
expect resp.http.Element == <undef>
expect resp.http.Element-Unique == <undef>
expect resp.http.Element-Exact == <undef>
expect resp.http.Element-First == "foobar"
expect resp.http.Element-Last == "foo"
expect resp.http.Element-Shortest == "foo"
expect resp.http.Element-Longest == "foobar"
} -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.element\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.element\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.element\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.element\(select=EXACT\): no element matched exactly$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbaz" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbazquux" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarb" -hdr "Select: EXACT"
expect_close
} -run
logexpect l1 -wait
......@@ -4,7 +4,7 @@ varnishtest "integer() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -108,9 +108,9 @@ client c1 {
expect resp.http.Integer-Longest == -2
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
logexpect l1 -v v1 -d 1 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.match\(\): subject string is NULL$}
expect * = Notice {^vmod_selector: s\.match\(\): subject string is NULL$}
expect * = End
} -run
......@@ -118,7 +118,7 @@ varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -138,18 +138,21 @@ varnish v1 -vcl {
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(\) called without prior match$}
expect * = VCL_Error {^vmod selector failure: s\.integer\(\) called without prior match$}
expect 0 = ReqHeader "Integer: 0"
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(\) called without prior match$}
expect * = VCL_Error {^vmod selector failure: s\.integer\(\) called without prior match$}
expect 0 = ReqHeader "Integer: 0"
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(6\): set has 5 elements$}
expect * = VCL_Error {^vmod selector failure: s\.integer\(6\): set has 5 elements$}
expect 0 = ReqHeader "Integer: 0"
expect * = VCL_return fail
expect * = End
} -start
......@@ -181,7 +184,7 @@ logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -227,7 +230,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -287,7 +290,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -310,13 +313,15 @@ varnish v1 -vcl {
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * * Begin req
expect * = ReqHeader "Integer-Exact: 3"
expect * = VCL_Error {^vmod selector error: s\.integer\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector failure: s\.integer\(select=UNIQUE\): 2 elements were matched$}
expect 0 = ReqHeader "Integer-Unique: 0"
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(select=EXACT\): no element matched exactly$}
expect * = VCL_Error {^vmod selector failure: s\.integer\(select=EXACT\): no element matched exactly$}
expect 0 = ReqHeader "Integer-Exact: 0"
expect * = VCL_return fail
expect * = End
} -start
......@@ -340,7 +345,7 @@ logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -364,8 +369,9 @@ varnish v1 -vcl {
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.integer\(\): integer not added for element 2$}
expect * = VCL_Error {^vmod selector failure: s\.integer\(\): integer not added for element 2$}
expect 0 = ReqHeader "Integer: 0"
expect * = VCL_return fail
expect * = End
} -start
......
......@@ -4,7 +4,7 @@ varnishtest "match() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new t = selector.set();
......@@ -53,7 +53,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new t = selector.set();
......@@ -89,7 +89,7 @@ client c1 {
varnish v1 -vcl {
import ${vmod_selector};
import std;
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
# 100 random choices from /usr/share/dict/words
......@@ -814,9 +814,73 @@ client c1 {
expect resp.http.Match == "false"
} -run
varnish v1 -vcl {
import ${vmod_selector};
backend b None;
sub vcl_init {
new s = selector.set();
s.add("foo");
s.compile();
}
sub vcl_recv {
if (req.http.Range-Error) {
set req.http.Range-Error = s.matched(2);
}
return (synth(200));
}
sub vcl_synth {
# For completeness. These are all true for .matched()
# after success, false after failure.
set resp.http.Match = s.hasprefix("foobar");
set resp.http.Matched-First = s.matched(select=FIRST);
set resp.http.Matched-Last = s.matched(select=LAST);
set resp.http.Matched-Shortest = s.matched(select=SHORTEST);
set resp.http.Matched-Longest = s.matched(select=LONGEST);
set resp.http.Non-Match = s.hasprefix("baz");
set resp.http.Non-Matched-First = s.matched(select=FIRST);
set resp.http.Non-Matched-Last = s.matched(select=LAST);
set resp.http.Non-Matched-Shortest = s.matched(select=SHORTEST);
set resp.http.Non-Matched-Longest = s.matched(select=LONGEST);
return (deliver);
}
}
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.Matched-First == "true"
expect resp.http.Matched-Last == "true"
expect resp.http.Matched-Shortest == "true"
expect resp.http.Matched-Longest == "true"
expect resp.http.Non-Match == "false"
expect resp.http.Non-Matched-First == "false"
expect resp.http.Non-Matched-Last == "false"
expect resp.http.Non-Matched-Shortest == "false"
expect resp.http.Non-Matched-Longest == "false"
txreq -hdr "Range-Error: oops"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.matched\(2\) out of range \(1 members\)$}
expect * = VCL_return fail
expect * = End
} -run
varnish v1 -errvcl {vmod selector failure: t.compile(): "foo" added more than once} {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new t = selector.set();
......@@ -828,7 +892,7 @@ varnish v1 -errvcl {vmod selector failure: t.compile(): "foo" added more than on
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new t = selector.set();
......@@ -841,6 +905,13 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: t\.add\(\) may only be called in vcl_init$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq
rxresp
......@@ -848,11 +919,7 @@ client c1 {
expect resp.reason == "VCL failed"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: t\.add\(\) may only be called in vcl_init$}
expect * = End
} -run
logexpect l1 -wait
logexpect l1 -v v1 -d 0 -g raw -q "vxid == 0 and VCL_Error" {
expect 0 0 VCL_Error {^VCL \S+ vmod selector n\.compile\(\): no entries were added, nothing to compile, n\.match\(\) will always fail}
......@@ -860,7 +927,7 @@ logexpect l1 -v v1 -d 0 -g raw -q "vxid == 0 and VCL_Error" {
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new t = selector.set();
......@@ -875,24 +942,29 @@ varnish v1 -vcl {
}
sub vcl_recv {
if (req.http.Late-Compile) {
s.compile();
}
return (synth(200));
}
sub vcl_synth {
set resp.http.Undef = t.match(req.http.No-Such-Header);
set resp.http.Nil = n.match("foo");
set resp.http.Not-Compiled = s.match("foo");
if (req.http.Nil) {
set resp.http.Nil = n.match("foo");
}
if (req.http.Not-Compiled) {
set resp.http.Not-Compiled = s.match("foo");
}
return (deliver);
}
}
logexpect l1 -wait
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
logexpect l1 -v v1 -d 0 -g vxid -q "Notice" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: t\.match\(\): subject string is NULL$}
expect * = VCL_Error {^vmod selector error: n\.match\(\): no entries were added$}
expect * = VCL_Error {^vmod selector error: s\.match\(\): set was not compiled$}
expect * = Notice {^vmod_selector: t\.match\(\): subject string is NULL$}
expect * = End
} -start
......@@ -901,7 +973,42 @@ client c1 {
rxresp
expect resp.status == 200
expect resp.http.Undef == "false"
expect resp.http.Nil == "false"
} -run
logexpect l1 -wait
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.compile\(\) may only be called in vcl_init$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: n\.match\(\): no entries were added$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.match\(\): set was not compiled$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Late-Compile: too late"
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
client c1 {
txreq -hdr "Nil: nil"
expect_close
} -run
client c1 {
txreq -hdr "Not-Compiled: not-compiled"
expect_close
} -run
logexpect l1 -wait
......
This diff is collapsed.
......@@ -4,7 +4,8 @@ varnishtest ".re_match() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
import std;
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -27,9 +28,10 @@ varnish v1 -vcl {
set resp.http.N-4 = s.re_match(req.http.Subject, 4);
set resp.http.N-5 = s.re_match(req.http.Subject, 5);
set resp.http.N--1 = s.re_match(req.http.Subject, -1);
set resp.http.N-0 = s.re_match(req.http.Subject, 0);
set resp.http.N-6 = s.re_match(req.http.Subject, 6);
if (req.http.N) {
set resp.http.N = s.re_match(req.http.Subject,
std.integer(req.http.N));
}
if (s.match(req.http.Word)) {
set resp.http.Match = s.re_match(req.http.Subject);
......@@ -75,10 +77,6 @@ client c1 {
expect resp.http.N-4 == "false"
expect resp.http.N-5 == "false"
expect resp.http.N--1 == "false"
expect resp.http.N-0 == "false"
expect resp.http.N-6 == "false"
expect resp.http.Match == "true"
expect resp.http.Match-Unique == resp.http.Match
expect resp.http.Match-Exact == resp.http.Match
......@@ -201,17 +199,41 @@ client c1 {
expect resp.http.Nonmatch-Longest == "false"
} -run
client c1 {
txreq -hdr "N: -1"
expect_close
} -run
client c1 {
txreq -hdr "N: 0"
expect_close
} -run
client c1 {
txreq -hdr "N: 6"
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.re_match\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(6\): set has 5 elements$}
expect * = VCL_Error {^vmod selector failure: s\.re_match\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.re_match\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.re_match\(6\): set has 5 elements$}
expect * = VCL_return fail
expect * = End
} -run
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -227,12 +249,28 @@ varnish v1 -vcl {
}
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.Match = s.re_match(req.http.Subject);
if (req.http.Select == "UNIQUE" && s.hasprefix(req.http.Word)) {
set resp.http.Match-Unique
= s.re_match(req.http.Subject, select=UNIQUE);
}
elsif (req.http.Select == "EXACT"
&& s.hasprefix(req.http.Word)) {
set resp.http.Match-Exact
= s.re_match(req.http.Subject, select=EXACT);
= s.re_match(req.http.Subject, select=EXACT);
}
elsif (s.hasprefix(req.http.Word)) {
if (s.nmatches() == 1) {
set resp.http.Match
= s.re_match(req.http.Subject);
set resp.http.Match-Unique
= s.re_match(req.http.Subject,
select=UNIQUE);
}
if (s.matched(select=EXACT)) {
set resp.http.Match-Exact
= s.re_match(req.http.Subject,
select=EXACT);
}
set resp.http.Match-First
= s.re_match(req.http.Subject, select=FIRST);
set resp.http.Match-Last
......@@ -246,35 +284,12 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * 1008 Begin req
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 2 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 3 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 4 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.re_match\(select=EXACT\): no element matched exactly$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo" -hdr "Subject: quux"
rxresp
expect resp.status == 200
expect resp.http.Match == "true"
expect resp.http.Match-Unique == "true"
expect resp.http.Match-Unique == resp.http.Match
expect resp.http.Match-Exact == "true"
expect resp.http.Match-First == "true"
expect resp.http.Match-Last == "true"
......@@ -284,8 +299,8 @@ client c1 {
txreq -hdr "Word: foobar" -hdr "Subject: baz"
rxresp
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.Match-Unique == "false"
expect resp.http.Match == <undef>
expect resp.http.Match-Unique == resp.http.Match
expect resp.http.Match-Exact == "true"
expect resp.http.Match-First == "true"
expect resp.http.Match-Last == "false"
......@@ -295,8 +310,8 @@ client c1 {
txreq -hdr "Word: foobarbaz" -hdr "Subject: bar"
rxresp
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.Match-Unique == "false"
expect resp.http.Match == <undef>
expect resp.http.Match-Unique == resp.http.Match
expect resp.http.Match-Exact == "true"
expect resp.http.Match-First == "true"
expect resp.http.Match-Last == "false"
......@@ -306,8 +321,8 @@ client c1 {
txreq -hdr "Word: foobarbazquux" -hdr "Subject: foo"
rxresp
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.Match-Unique == "false"
expect resp.http.Match == <undef>
expect resp.http.Match-Unique == resp.http.Match
expect resp.http.Match-Exact == "true"
expect resp.http.Match-First == "true"
expect resp.http.Match-Last == "false"
......@@ -317,20 +332,62 @@ client c1 {
txreq -hdr "Word: foobarb" -hdr "Subject: baz"
rxresp
expect resp.status == 200
expect resp.http.Match == "false"
expect resp.http.Match-Unique == "false"
expect resp.http.Match-Exact == "false"
expect resp.http.Match == <undef>
expect resp.http.Match-Unique == resp.http.Match
expect resp.http.Match-Exact == <undef>
expect resp.http.Match-First == "true"
expect resp.http.Match-Last == "false"
expect resp.http.Match-Shortest == "false"
expect resp.http.Match-Longest == "true"
} -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.re_match\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.re_match\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.re_match\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.re_match\(select=EXACT\): no element matched exactly$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar" -hdr "Subject: baz" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbaz" -hdr "Subject: bar" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbazquux" -hdr "Subject: foo" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarb" -hdr "Subject: baz" -hdr "Select: EXACT"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -353,7 +410,8 @@ varnish v1 -vcl {
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.re_match\(\): regex not added for element 2$}
expect * = VCL_Error {^vmod selector failure: s\.re_match\(\): regex not added for element 2$}
expect * = VCL_return fail
expect * = End
} -start
......@@ -364,16 +422,14 @@ client c1 {
expect resp.http.Match == "true"
txreq -hdr "Word: bar" -hdr "Subject: foo"
rxresp
expect resp.status == 200
expect resp.http.Match == "false"
expect_close
} -run
logexpect l1 -wait
varnish v1 -errvcl {vmod selector failure: s.add(): cannot compile regular expression '(':} {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......
......@@ -4,7 +4,8 @@ varnishtest "string() method"
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
import std;
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -27,9 +28,9 @@ varnish v1 -vcl {
set resp.http.N-4 = s.string(4);
set resp.http.N-5 = s.string(5);
set resp.http.N--1 = s.string(-1);
set resp.http.N-0 = s.string(0);
set resp.http.N-6 = s.string(6);
if (req.http.N) {
set resp.http.N = s.string(std.integer(req.http.N));
}
if (s.match(req.http.Word)) {
set resp.http.String = s.string();
......@@ -56,10 +57,6 @@ client c1 {
expect resp.http.N-4 == "xuuq"
expect resp.http.N-5 == "raboof"
expect resp.http.N--1 == ""
expect resp.http.N-0 == ""
expect resp.http.N-6 == ""
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
......@@ -116,17 +113,41 @@ client c1 {
expect resp.http.String-Longest == "raboof"
} -run
client c1 {
txreq -hdr "N: -1"
expect_close
} -run
client c1 {
txreq -hdr "N: 0"
expect_close
} -run
client c1 {
txreq -hdr "N: 6"
expect_close
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.string\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.string\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.string\(6\): set has 5 elements$}
expect * = VCL_Error {^vmod selector failure: s\.string\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(6\): set has 5 elements$}
expect * = VCL_return fail
expect * = End
} -run
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -142,10 +163,23 @@ varnish v1 -vcl {
}
sub vcl_synth {
if (s.hasprefix(req.http.Word)) {
set resp.http.String = s.string();
if (req.http.Select == "UNIQUE" && s.hasprefix(req.http.Word)) {
set resp.http.String-Unique = s.string(select=UNIQUE);
}
elsif (req.http.Select == "EXACT"
&& s.hasprefix(req.http.Word)) {
set resp.http.String-Exact = s.string(select=EXACT);
}
elsif (s.hasprefix(req.http.Word)) {
if (s.nmatches() == 1) {
set resp.http.String = s.string();
set resp.http.String-Unique
= s.string(select=UNIQUE);
}
if (s.matched(select=EXACT)) {
set resp.http.String-Exact
= s.string(select=EXACT);
}
set resp.http.String-First = s.string(select=FIRST);
set resp.http.String-Last = s.string(select=LAST);
set resp.http.String-Shortest
......@@ -157,29 +191,6 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect * 1009 Begin req
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 2 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 3 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 4 elements were matched$}
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.string\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_Error {^vmod selector error: s\.string\(select=EXACT\): no element matched exactly$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
......@@ -195,8 +206,8 @@ client c1 {
txreq -hdr "Word: foobar"
rxresp
expect resp.status == 200
expect resp.http.String == ""
expect resp.http.String-Unique == ""
expect resp.http.String == <undef>
expect resp.http.String-Unique == <undef>
expect resp.http.String-Exact == "3"
expect resp.http.String-First == "3"
expect resp.http.String-Last == "4"
......@@ -206,8 +217,8 @@ client c1 {
txreq -hdr "Word: foobarbaz"
rxresp
expect resp.status == 200
expect resp.http.String == ""
expect resp.http.String-Unique == ""
expect resp.http.String == <undef>
expect resp.http.String-Unique == <undef>
expect resp.http.String-Exact == "2"
expect resp.http.String-First == "2"
expect resp.http.String-Last == "4"
......@@ -217,8 +228,8 @@ client c1 {
txreq -hdr "Word: foobarbazquux"
rxresp
expect resp.status == 200
expect resp.http.String == ""
expect resp.http.String-Unique == ""
expect resp.http.String == <undef>
expect resp.http.String-Unique == <undef>
expect resp.http.String-Exact == "1"
expect resp.http.String-First == "1"
expect resp.http.String-Last == "4"
......@@ -228,20 +239,62 @@ client c1 {
txreq -hdr "Word: foobarb"
rxresp
expect resp.status == 200
expect resp.http.String == ""
expect resp.http.String-Unique == ""
expect resp.http.String-Exact == ""
expect resp.http.String == <undef>
expect resp.http.String-Unique == <undef>
expect resp.http.String-Exact == <undef>
expect resp.http.String-First == "3"
expect resp.http.String-Last == "4"
expect resp.http.String-Shortest == "4"
expect resp.http.String-Longest == "3"
} -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(select=UNIQUE\): 2 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(select=UNIQUE\): 3 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(select=UNIQUE\): 4 elements were matched$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(select=EXACT\): no element matched exactly$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Word: foobar" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbaz" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarbazquux" -hdr "Select: UNIQUE"
expect_close
} -run
client c1 {
txreq -hdr "Word: foobarb" -hdr "Select: EXACT"
expect_close
} -run
logexpect l1 -wait
varnish v1 -vcl {
import ${vmod_selector};
backend b { .host = "${bad_ip}"; }
backend b None;
sub vcl_init {
new s = selector.set();
......@@ -262,22 +315,23 @@ varnish v1 -vcl {
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.string\(\): string not added for element 2$}
expect * = End
} -start
client c1 {
txreq -hdr "Word: foo"
rxresp
expect resp.status == 200
expect resp.http.String == "foo"
} -run
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.string\(\): string not added for element 2$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq -hdr "Word: bar"
rxresp
expect resp.status == 200
expect resp.http.String == ""
expect_close
} -run
logexpect l1 -wait
......@@ -147,28 +147,49 @@ varnish v1 -vcl {
}
sub vcl_synth {
set resp.http.Sub = s.sub("foo", "bar");
set resp.http.Sub-False = s.sub("foo", "bar", false);
set resp.http.Suball = s.sub("foo", "bar", true);
if (req.http.Sub) {
set resp.http.Sub = s.sub("foo", "bar");
}
if (req.http.Sub-False) {
set resp.http.Sub-False = s.sub("foo", "bar", false);
}
if (req.http.Suball) {
set resp.http.Suball = s.sub("foo", "bar", true);
}
return (deliver);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^vmod selector error: s\.sub\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.sub\(\) called without prior match$}
expect * = VCL_Error {^vmod selector error: s\.sub\(\) called without prior match$}
expect * = VCL_Error {^vmod selector failure: s\.sub\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.sub\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
expect 0 * Begin req
expect * = VCL_Error {^vmod selector failure: s\.sub\(\) called without prior match$}
expect * = VCL_return fail
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Sub == ""
expect resp.http.Sub-False == ""
expect resp.http.Suball == ""
txreq -hdr "Sub: sub"
expect_close
} -run
client c1 {
txreq -hdr "Sub-False: sub-false"
expect_close
} -run
client c1 {
txreq -hdr "Suball: suball"
expect_close
} -run
logexpect l1 -wait
......
......@@ -50,12 +50,11 @@
#define VFAIL(ctx, fmt, ...) \
VRT_fail((ctx), "vmod selector failure: " fmt, __VA_ARGS__)
#define VERR(ctx, fmt, ...) \
VSLb((ctx)->vsl, SLT_VCL_Error, "vmod selector error: " fmt, \
__VA_ARGS__)
#define VERRNOMEM(ctx, fmt, ...) \
VERR((ctx), "out of space: " fmt, __VA_ARGS__)
VFAIL((ctx), "out of space: " fmt, __VA_ARGS__)
#define VNOTICE(ctx, fmt, ...) \
VSLb((ctx)->vsl, SLT_Notice, "vmod_selector: " fmt, __VA_ARGS__)
struct entry {
unsigned magic;
......@@ -446,15 +445,16 @@ vmod_set_match(VRT_CTX, struct vmod_selector_set *set, VCL_STRING subject)
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
if (set->nmembers == 0) {
VERR(ctx, "%s.match(): no entries were added", set->vcl_name);
VFAIL(ctx, "%s.match(): no entries were added", set->vcl_name);
return (0);
}
if (set->hash == NULL) {
VERR(ctx, "%s.match(): set was not compiled", set->vcl_name);
VFAIL(ctx, "%s.match(): set was not compiled", set->vcl_name);
return (0);
}
if (subject == NULL) {
VERR(ctx, "%s.match(): subject string is NULL", set->vcl_name);
VNOTICE(ctx, "%s.match(): subject string is NULL",
set->vcl_name);
return (0);
}
......@@ -503,18 +503,18 @@ vmod_set_hasprefix(VRT_CTX, struct vmod_selector_set *set, VCL_STRING subject)
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
if (set->nmembers == 0) {
VERR(ctx, "%s.hasprefix(): no entries were added",
set->vcl_name);
VFAIL(ctx, "%s.hasprefix(): no entries were added",
set->vcl_name);
return (0);
}
if (set->origo == NULL) {
VERR(ctx, "%s.hasprefix(): set was not compiled",
set->vcl_name);
VFAIL(ctx, "%s.hasprefix(): set was not compiled",
set->vcl_name);
return (0);
}
if (subject == NULL) {
VERR(ctx, "%s.hasprefix(): subject string is NULL",
set->vcl_name);
VNOTICE(ctx, "%s.hasprefix(): subject string is NULL",
set->vcl_name);
return (0);
}
......@@ -566,8 +566,8 @@ get_existing_match_data(VRT_CTX,
task = VRT_priv_task(ctx, set);
AN(task);
if (task->priv == NULL) {
VERR(ctx, "%s.%s() called without prior match", set->vcl_name,
method);
VFAIL(ctx, "%s.%s() called without prior match", set->vcl_name,
method);
return (NULL);
}
WS_Assert_Allocated(ctx->ws, task->priv, sizeof(*match));
......@@ -590,16 +590,17 @@ vmod_set_nmatches(VRT_CTX, struct vmod_selector_set *set)
}
VCL_BOOL
vmod_set_matched(VRT_CTX, struct vmod_selector_set *set, VCL_INT idx)
vmod_set_matched(VRT_CTX, struct VPFX(selector_set) *set, VCL_INT idx,
VCL_ENUM selects)
{
struct match_data *match;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
if (idx < 1 || idx > set->nmembers) {
VERR(ctx, "%s.matched(%ld) out of range (%d members)",
set->vcl_name, idx, set->nmembers);
if (idx > set->nmembers) {
VFAIL(ctx, "%s.matched(%ld) out of range (%d members)",
set->vcl_name, idx, set->nmembers);
return (0);
}
......@@ -610,12 +611,21 @@ vmod_set_matched(VRT_CTX, struct vmod_selector_set *set, VCL_INT idx)
AN(match->indices);
WS_Assert_Allocated(ctx->ws, match->indices,
match->n * sizeof(unsigned));
/* XXX search algorithm? */
idx--;
for (unsigned i = 0; i < match->n; i++)
if (match->indices[i] == idx)
return (1);
return (0);
if (idx > 0) {
/* XXX search algorithm? */
idx--;
for (unsigned i = 0; i < match->n; i++)
if (match->indices[i] == idx)
return (1);
return (0);
}
if (selects == VENUM(UNIQUE))
return (match->n == 1);
if (selects == VENUM(EXACT))
return (match->exact != UINT_MAX);
return (1);
}
static unsigned
......@@ -625,8 +635,8 @@ select(VRT_CTX, const struct match_data * const restrict match,
{
if (selects == VENUM(EXACT)) {
if (match->exact == UINT_MAX)
VERR(ctx, "%s.%s(select=EXACT): "
"no element matched exactly", obj, method);
VFAIL(ctx, "%s.%s(select=EXACT): "
"no element matched exactly", obj, method);
return match->exact;
}
if (match->n == 1)
......@@ -635,8 +645,8 @@ select(VRT_CTX, const struct match_data * const restrict match,
switch (selects[0]) {
case 'U':
assert(selects == VENUM(UNIQUE));
VERR(ctx, "%s.%s(select=UNIQUE): %d elements were matched",
obj, method, match->n);
VFAIL(ctx, "%s.%s(select=UNIQUE): %d elements were matched",
obj, method, match->n);
return (UINT_MAX);
case 'L':
if (selects == VENUM(LAST))
......@@ -677,8 +687,8 @@ get_idx(VRT_CTX, VCL_INT n, const struct vmod_selector_set * const restrict set,
if (n > 0) {
if (n > set->nmembers) {
VERR(ctx, "%s.%s(%ld): set has %d elements",
set->vcl_name, method, n, set->nmembers);
VFAIL(ctx, "%s.%s(%ld): set has %d elements",
set->vcl_name, method, n, set->nmembers);
return (UINT_MAX);
}
return (n - 1);
......@@ -712,8 +722,8 @@ check_added(VRT_CTX, const struct vmod_selector_set * const restrict set,
const char * const restrict type)
{
if (!is_added(set, idx, bitmap)) {
VERR(ctx, "%s.%s(): %s not added for element %u", set->vcl_name,
method, type, idx + 1);
VFAIL(ctx, "%s.%s(): %s not added for element %u",
set->vcl_name, method, type, idx + 1);
return (0);
}
return (1);
......@@ -771,14 +781,10 @@ vmod_set_integer(VRT_CTX, struct vmod_selector_set * set, VCL_INT n,
CHECK_OBJ_NOTNULL(set, VMOD_SELECTOR_SET_MAGIC);
idx = get_idx(ctx, n, set, "integer", selects);
if (idx == UINT_MAX) {
*ctx->handling = VCL_RET_FAIL;
if (idx == UINT_MAX)
return (0);
}
if (!check_added(ctx, set, idx, INTEGER, "integer", "integer")) {
*ctx->handling = VCL_RET_FAIL;
if (!check_added(ctx, set, idx, INTEGER, "integer", "integer"))
return (0);
}
return (set->table[idx]->integer);
}
......
......@@ -32,7 +32,7 @@ SYNOPSIS
# Match properties
INT <obj>.nmatches()
BOOL <obj>.matched(INT)
BOOL <obj>.matched([INT n] [, ENUM select])
INT <obj>.which([ENUM select])
# Retrieving objects after match
......@@ -470,7 +470,9 @@ Example::
set bereq.backend = myset.backend(select=UNIQUE);
}
$Method BOOL .matched(INT)
$Method BOOL .matched(INT n=0,
ENUM {UNIQUE, EXACT, FIRST, LAST, SHORTEST, LONGEST}
select=UNIQUE)
After a successful ``.match()`` or ``.hasprefix()`` call for the same
set object in the same task scope, return ``true`` if the element
......
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