varnishtest "shard director LAZY and layering"

server s1 -repeat 3 {
	rxreq
	txresp -body "ech3Ooj"
} -start

server s2 -repeat 3 {
	rxreq
	txresp -body "ieQu2qua"
} -start

server s3 -repeat 3 {
	rxreq
	txresp -body "xiuFi3Pe"
} -start

varnish v1 -vcl+backend {
	import std;
	import directors;

	sub vcl_init {
	    new vd = directors.shard();
	    if (!vd.add_backend(s1)) {
		return(fail("add s1 failed"));
	    }
	    if (!vd.add_backend(s2)) {
		return(fail("add s2 failed"));
	    }
	    if (!vd.add_backend(s3)) {
		return(fail("add s3 failed"));
	    }
	    if (!vd.reconfigure(replicas=25)) {
		return(fail("reconfigure failed"));
	    }

	    new l = directors.shard();
	    new lp = directors.shard_param();
	    l.associate();
	    l.associate(lp.use());
	    if (!l.add_backend(s1)) {
		return(fail("add s1 failed"));
	    }
	    if (!l.add_backend(s2)) {
		return(fail("add s2 failed"));
	    }
	    if (!l.add_backend(s3)) {
		return(fail("add s3 failed"));
	    }
	    if (!l.reconfigure(replicas=25)) {
		return(fail("reconfigure failed"));
	    }
	    new ll = directors.round_robin();
	    ll.add_backend(l.backend());
	}

	sub vcl_recv {
	    return(pass);
	}

	sub backend_fetch_direct {
	    if (bereq.url == "/1") {
		set bereq.backend =
		    vd.backend(resolve=LAZY, by=KEY, key=1);
	    } else
	    if (bereq.url == "/2") {
		set bereq.backend =
		  vd.backend(resolve=LAZY, by=KEY, key=2147483647);
	    } else
	    if (bereq.url == "/3") {
		set bereq.backend =
		  vd.backend(resolve=LAZY, by=KEY, key=4294967295);
	    }
	    set bereq.http.bereq-now-1 = vd.backend(resolve=NOW);
	    set bereq.http.bereq-now-mod =
		vd.backend(resolve=NOW, alt=1);
	    set bereq.http.bereq-now-2 = vd.backend(resolve=NOW);
	}

	sub backend_fetch_layered {
	    set bereq.backend = ll.backend();
	    if (bereq.url == "/1") {
		lp.set(by=KEY, key=1);
	    } else
	    if (bereq.url == "/2") {
		lp.set(by=KEY, key=2147483647);
	    } else
	    if (bereq.url == "/3") {
		lp.set(by=KEY, key=4294967295);
	    }
	    set bereq.http.bereq-now-1 = l.backend(resolve=NOW);
	    set bereq.http.bereq-now-mod =
		l.backend(resolve=NOW, alt=1);
	    set bereq.http.bereq-now-2 = l.backend(resolve=NOW);
	}

	sub vcl_backend_fetch {
	    if (bereq.http.layered) {
		call backend_fetch_layered;
	    } else if (bereq.http.resolve) {
		call backend_fetch_layered;
		set bereq.backend = bereq.backend.resolve();
	    } else {
		call backend_fetch_direct;
	    }
	}

	sub vcl_backend_response {
	    if (bereq.http.layered || bereq.http.resolve) {
		set beresp.http.healthy = std.healthy(ll.backend());
		set beresp.http.backend-now = l.backend(resolve=NOW);
	    } else {
		set beresp.http.healthy = std.healthy(
		  vd.backend(resolve=LAZY, by=KEY, key=1));
	    }
	    set beresp.http.director = bereq.backend;
	    set beresp.http.backend = beresp.backend;
	    set beresp.http.bereq-now-1 = bereq.http.bereq-now-1;
	    set beresp.http.bereq-now-mod = bereq.http.bereq-now-mod;
	    set beresp.http.bereq-now-2 = bereq.http.bereq-now-2;
	}
} -start


client c1 {
	txreq -url /1
	rxresp
	expect resp.body == "ech3Ooj"
	expect resp.http.healthy == "true"
	expect resp.http.director == "vd"
	expect resp.http.backend == "s1"
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /2
	rxresp
	expect resp.body == "ieQu2qua"
	expect resp.http.healthy == "true"
	expect resp.http.director == "vd"
	expect resp.http.backend == "s2"
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /3
	rxresp
	expect resp.body == "xiuFi3Pe"
	expect resp.http.healthy == "true"
	expect resp.http.director == "vd"
	expect resp.http.backend == "s3"
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /1 -hdr "layered: true"
	rxresp
	expect resp.body == "ech3Ooj"
	expect resp.http.healthy == "true"
	expect resp.http.director == "ll"
	expect resp.http.backend == "s1"
	expect resp.http.backend == resp.http.backend-now
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /2 -hdr "layered: true"
	rxresp
	expect resp.body == "ieQu2qua"
	expect resp.http.healthy == "true"
	expect resp.http.director == "ll"
	expect resp.http.backend == "s2"
	expect resp.http.backend == resp.http.backend-now
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /3 -hdr "layered: true"
	rxresp
	expect resp.body == "xiuFi3Pe"
	expect resp.http.healthy == "true"
	expect resp.http.director == "ll"
	expect resp.http.backend == "s3"
	expect resp.http.backend == resp.http.backend-now
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /1 -hdr "resolve: true"
	rxresp
	expect resp.body == "ech3Ooj"
	expect resp.http.healthy == "true"
	expect resp.http.director == "s1"
	expect resp.http.backend == "s1"
	expect resp.http.backend == resp.http.backend-now
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /2 -hdr "resolve: true"
	rxresp
	expect resp.body == "ieQu2qua"
	expect resp.http.healthy == "true"
	expect resp.http.director == "s2"
	expect resp.http.backend == "s2"
	expect resp.http.backend == resp.http.backend-now
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2

	txreq -url /3 -hdr "resolve: true"
	rxresp
	expect resp.body == "xiuFi3Pe"
	expect resp.http.healthy == "true"
	expect resp.http.director == "s3"
	expect resp.http.backend == "s3"
	expect resp.http.backend == resp.http.backend-now
	expect resp.http.backend == resp.http.bereq-now-1
	expect resp.http.backend != resp.http.bereq-now-mod
	expect resp.http.backend == resp.http.bereq-now-2
} -run
