Commit c2ede2a0 authored by Geoff Simmons's avatar Geoff Simmons

Add ENUM select to the set.string() and .backend() methods.

parent 3d9d5c5b
Pipeline #337 skipped
......@@ -892,7 +892,7 @@ set.string
::
STRING set.string(INT n=0)
STRING set.string(INT n=0, ENUM {FIRST,LAST} select=0)
.. _func_set.backend:
......@@ -901,7 +901,7 @@ set.backend
::
BACKEND set.backend(INT n=0)
BACKEND set.backend(INT n=0, ENUM {FIRST,LAST} select=0)
.. _func_version:
......
......@@ -4,19 +4,13 @@ varnishtest "set .string() and .backend() methods"
varnish v1 -vcl {
import ${vmod_re2};
backend b1 { .host = "${bad_ip}"; }
backend b2 { .host = "${bad_ip}"; }
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new s = re2.set();
s.add("foo", "baz");
s.add("bar", "quux");
s.compile();
new b = re2.set();
b.add("foo", backend=b1);
b.add("bar", backend=b2);
b.compile();
}
sub vcl_recv {
......@@ -38,10 +32,70 @@ varnish v1 -vcl {
set resp.http.s-fail-match = s.match("fail");
set resp.http.s-fail-n = s.nmatches();
set resp.http.s-fail-str = s.string();
set resp.http.s-toomany-match = s.match("foobar");
set resp.http.s-toomany-n = s.nmatches();
set resp.http.s-toomany-str = s.string();
set resp.http.s-many-match = s.match("foobar");
set resp.http.s-many-n = s.nmatches();
set resp.http.s-many-str = s.string();
set resp.http.s-many-first = s.string(select=FIRST);
set resp.http.s-many-last = s.string(select=LAST);
set resp.http.s-outofrange = s.string(3);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.s-str-1 == "baz"
expect resp.http.s-str-2 == "quux"
expect resp.http.s-before-match == ""
expect resp.http.s-foo-match == "true"
expect resp.http.s-foo-n == 1
expect resp.http.s-foo-str == "baz"
expect resp.http.s-bar-match == "true"
expect resp.http.s-bar-n == 1
expect resp.http.s-bar-str == "quux"
expect resp.http.s-bar-str-0 == resp.http.s-bar-str
expect resp.http.s-bar-str-1 == resp.http.s-bar-str
expect resp.http.s-fail-match == "false"
expect resp.http.s-fail-n == 0
expect resp.http.s-fail-str == ""
expect resp.http.s-many-match == "true"
expect resp.http.s-many-n == 2
expect resp.http.s-many-str == ""
expect resp.http.s-many-first == "baz"
expect resp.http.s-many-last == "quux"
expect resp.http.s-outofrange == ""
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: s.string.. called without prior match$"
expect * = VCL_Error "^vmod re2 error: s.string.0.: previous match was unsuccessful$"
expect * = VCL_Error "^vmod re2 error: s.string.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: s.string.3.: set has 2 patterns$"
expect * = End
} -run
varnish v1 -vcl {
import ${vmod_re2};
backend b1 { .host = "${bad_ip}"; }
backend b2 { .host = "${bad_ip}"; }
sub vcl_init {
new b = re2.set();
b.add("foo", backend=b1);
b.add("bar", backend=b2);
b.compile();
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.b-backend-1 = b.backend(1);
set resp.http.b-backend-2 = b.backend(2);
set resp.http.b-before-match = b.backend();
......@@ -56,37 +110,31 @@ varnish v1 -vcl {
set resp.http.b-fail-match = b.match("fail");
set resp.http.b-fail-n = b.nmatches();
set resp.http.b-fail-backend = b.backend();
set resp.http.b-toomany-match = b.match("foobar");
set resp.http.b-toomany-n = b.nmatches();
set resp.http.b-toomany-backend = b.backend();
set resp.http.s-outofrange = s.string(3);
set resp.http.b-many-match = b.match("foobar");
set resp.http.b-many-n = b.nmatches();
set resp.http.b-many-backend = b.backend();
set resp.http.b-many-first = b.backend(select=FIRST);
set resp.http.b-many-last = b.backend(select=LAST);
set resp.http.b-outofrange = b.backend(3);
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: b.backend.. called without prior match$"
expect * = VCL_Error "^vmod re2 error: b.backend.0.: previous match was unsuccessful$"
expect * = VCL_Error "^vmod re2 error: b.backend.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: b.backend.3.: set has 2 patterns$"
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.s-str-1 == "baz"
expect resp.http.s-str-2 == "quux"
expect resp.http.s-before-match == ""
expect resp.http.s-foo-match == "true"
expect resp.http.s-foo-n == 1
expect resp.http.s-foo-str == "baz"
expect resp.http.s-bar-match == "true"
expect resp.http.s-bar-n == 1
expect resp.http.s-bar-str == "quux"
expect resp.http.s-bar-str-0 == resp.http.s-bar-str
expect resp.http.s-bar-str-1 == resp.http.s-bar-str
expect resp.http.s-fail-match == "false"
expect resp.http.s-fail-n == 0
expect resp.http.s-fail-str == ""
expect resp.http.s-toomany-match == "true"
expect resp.http.s-toomany-n == 2
expect resp.http.s-toomany-str == ""
expect resp.http.b-backend-1 == "b1"
expect resp.http.b-backend-2 == "b2"
expect resp.http.b-before-match == ""
......@@ -101,24 +149,12 @@ client c1 {
expect resp.http.b-fail-match == "false"
expect resp.http.b-fail-n == 0
expect resp.http.b-fail-backend == ""
expect resp.http.b-toomany-match == "true"
expect resp.http.b-toomany-n == 2
expect resp.http.b-toomany-backend == ""
expect resp.http.s-outofrange == ""
expect resp.http.b-many-match == "true"
expect resp.http.b-many-n == 2
expect resp.http.b-many-backend == ""
expect resp.http.b-many-first == "b1"
expect resp.http.b-many-last == "b2"
expect resp.http.b-outofrange == ""
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error "^vmod re2 error: s.string.. called without prior match$"
expect * = VCL_Error "^vmod re2 error: s.string.0.: previous match was unsuccessful$"
expect * = VCL_Error "^vmod re2 error: s.string.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: b.backend.. called without prior match$"
expect * = VCL_Error "^vmod re2 error: b.backend.0.: previous match was unsuccessful$"
expect * = VCL_Error "^vmod re2 error: b.backend.0.: 2 successful matches$"
expect * = VCL_Error "^vmod re2 error: s.string.3.: set has 2 patterns$"
expect * = VCL_Error "^vmod re2 error: b.backend.3.: set has 2 patterns$"
expect * = End
} -run
logexpect l1 -wait
......@@ -811,9 +811,11 @@ vmod_set_nmatches(VRT_CTX, struct vmod_re2_set *set)
}
static int
get_match_idx(VRT_CTX, struct vmod_re2_set *set, VCL_INT n, const char *method)
get_match_idx(VRT_CTX, struct vmod_re2_set *set, VCL_INT n, VCL_ENUM selects,
const char *method)
{
struct task_set_match *task;
int idx = 0;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(set, VMOD_RE2_SET_MAGIC);
......@@ -837,28 +839,34 @@ get_match_idx(VRT_CTX, struct vmod_re2_set *set, VCL_INT n, const char *method)
return -1;
}
if (task->nmatches > 1) {
VERR(ctx, "%s.%s(%lld): %d successful matches", set->vcl_name,
method, n, task->nmatches);
return -1;
if (selects == NULL) {
VERR(ctx, "%s.%s(%lld): %d successful matches",
set->vcl_name, method, n, task->nmatches);
return -1;
}
if (strcmp(selects, "LAST") == 0)
idx = task->nmatches - 1;
else
AZ(strcmp(selects, "FIRST"));
}
WS_Assert_Allocated(ctx->ws, task->matches,
task->nmatches * sizeof(int));
return task->matches[0];
return task->matches[idx];
}
VCL_STRING
vmod_set_string(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
vmod_set_string(VRT_CTX, struct vmod_re2_set *set, VCL_INT n, VCL_ENUM selects)
{
int idx = get_match_idx(ctx, set, n, "string");
int idx = get_match_idx(ctx, set, n, selects, "string");
if (idx < 0)
return NULL;
return set->string[idx];
}
VCL_BACKEND
vmod_set_backend(VRT_CTX, struct vmod_re2_set *set, VCL_INT n)
vmod_set_backend(VRT_CTX, struct vmod_re2_set *set, VCL_INT n, VCL_ENUM selects)
{
int idx = get_match_idx(ctx, set, n, "backend");
int idx = get_match_idx(ctx, set, n, selects, "backend");
if (idx < 0)
return NULL;
return set->backend[idx];
......
......@@ -760,9 +760,9 @@ Example::
+ " patterns from the set");
}
$Method STRING .string(INT n=0)
$Method STRING .string(INT n=0, ENUM {FIRST, LAST} select=0)
$Method BACKEND .backend(INT n=0)
$Method BACKEND .backend(INT n=0, ENUM {FIRST, LAST} select=0)
$Function STRING version()
......
......@@ -158,6 +158,7 @@ vre2set_match(vre2set *set, const char * const subject, int * const match,
if (m.size() * sizeof(int) > buflen)
return "insufficient space to copy match data";
*nmatches = m.size();
sort(m.begin(), m.end());
memcpy(buf, m.data(), *nmatches * sizeof(int));
}
return NULL;
......
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