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