vtest "More VCL coverage"

server s1 {
	rxreq
	expect req.http.c_id == "Samuel B. Nobody"
	txresp
	rxreq
	expect req.http.c_id == ${localhost}
	txresp
} -start

# Test max_vcl param
vinyl v1 -arg "-i J.F.Nobody" -vcl+backend { } -start

vinyl v1 -cliok "param.set max_vcl 2"
vinyl v1 -cliok "param.set max_vcl_handling 2"

vinyl v1 -vcl+backend { }
vinyl v1 -errvcl {Too many (2) VCLs already loaded} {}

vinyl v1 -cliok "param.set max_vcl_handling 1"

vinyl v1 -cliexpect "Remember to vcl.discard the old/unused VCLs." \
	{vcl.inline foobar "vcl 4.1; backend b1 {.host=\"${s1_addr}\";}"}

vinyl v1 -cliok "param.set max_vcl 100"

vinyl v1 -syntax 4.0 -vcl+backend {

	import std;
	import directors;

	sub vcl_init {
		new rr = directors.round_robin();
		rr.add_backend(s1);
	}

	sub vcl_recv {
		set client.identity = "Samuel B. Nobody";
		set req.backend_hint = rr.backend();
	}

	sub vcl_deliver {
		set resp.http.server_port = std.port(server.ip);
		set resp.http.server_port_foo = std.port(server.ip) + "_foo";
		set resp.http.ttl1 = (req.max_age + 10s);
		set resp.http.ttl2 = req.max_age + 10s;
		set resp.http.id = server.identity;
		set resp.http.esi = req.esi;
		set resp.http.be = req.backend_hint;
		set resp.http.c_id = client.identity;
		set resp.http.l_ip = local.ip;
		set resp.http.r_ip = remote.ip;
		if (obj.uncacheable) { }
		set resp.http.o_age = obj.age;
		set resp.http.o_ttl = obj.ttl;
		set resp.http.o_grace = obj.grace;
		set resp.http.o_keep = obj.keep;
	}

	sub vcl_backend_response {
		set beresp.http.bereq_backend = bereq.backend;
		set beresp.http.beresp_backend = beresp.backend;
		set beresp.http.keep = beresp.keep;
		set beresp.http.stv = beresp.storage;
		set beresp.http.be_ip = beresp.backend.ip;
		set beresp.http.be_nm = beresp.backend.name;
		set beresp.http.unc = bereq.uncacheable;
		if (beresp.ttl > 3 s) {
			set beresp.http.ttl = "long";
		} else {
			set beresp.http.ttl = "short";
		}
	}

	sub vcl_hit {
		if (obj.status != 200) { return(synth(700)); }
		if (obj.proto) { }
		if (obj.reason) { }
		if (obj.keep > 1m) { }
		if (obj.grace < 3m) {
			return (deliver);
		}
		if (obj.ttl < 3m) {
			return (deliver);
		}
	}

	sub vcl_backend_fetch {
		set bereq.http.c_id = client.identity;
		if (bereq.between_bytes_timeout < 10s) {
			set bereq.http.quick = "please";
		}
		if (bereq.connect_timeout < 10s) {
			set bereq.http.hello = "please";
		}
		set bereq.connect_timeout = 10s;
	}

}

client c1 {
	txreq
	rxresp
	expect resp.status == 200
	expect resp.http.bereq_backend == "rr"
	expect resp.http.beresp_backend == "s1"
	expect resp.http.be_ip == "${localhost}"
	expect resp.http.be_nm == "s1"
	expect resp.http.be == "rr"

	txreq
	rxresp
} -run

vinyl v1 -syntax 4.0 -errvcl {Symbol not found: 'sess.xid' (Only available when 4.1 <= VCL syntax)} {
	sub vcl_recv {
		set req.http.Sess-XID = sess.xid;
	}
}

vinyl v1 -syntax 4.0 -errvcl {Symbol not found: 'sess.xid' (Only available when 4.1 <= VCL syntax)} {
	sub vcl_backend_fetch {
		set bereq.http.Sess-XID = sess.xid;
	}
}

vinyl v1 -syntax 4.0 -errvcl {Symbol not found: 'local.endpoint' (Only available when 4.1 <= VCL syntax)} {
	sub vcl_recv {
		set req.http.Endpoint = local.endpoint;
	}
}

vinyl v1 -syntax 4.0 -errvcl {Symbol not found: 'local.endpoint' (Only available when 4.1 <= VCL syntax)} {
	sub vcl_backend_fetch {
		set bereq.http.Endpoint = local.endpoint;
	}
}

vinyl v1 -syntax 4.0 -errvcl {Symbol not found: 'local.socket' (Only available when 4.1 <= VCL syntax)} {
	sub vcl_recv {
		set req.http.Socket = local.socket;
	}
}

vinyl v1 -syntax 4.0 -errvcl {Symbol not found: 'local.socket' (Only available when 4.1 <= VCL syntax)} {
	sub vcl_backend_fetch {
		set bereq.http.Socket = local.socket;
	}
}

vinyl v1 -syntax 4.1 -vcl+backend {
	sub vcl_backend_fetch {
		set bereq.http.c_id = client.identity;
	}

	sub vcl_backend_response {
		set beresp.http.B-Sess-XID = sess.xid;
		set beresp.http.B-Endpoint = local.endpoint;
		set beresp.http.B-Socket = local.socket;
	}

	sub vcl_deliver {
		set resp.http.C-Sess-XID = sess.xid;
		set resp.http.C-Endpoint = local.endpoint;
		set resp.http.C-Socket = local.socket;
	}
}

client c1 {
	txreq -url "/uncached"
	rxresp
	expect resp.status == 200
	expect resp.http.C-Sess-XID ~ "^[0-9]+$"
	expect resp.http.B-Sess-XID ~ "^[0-9]+$"
	expect resp.http.C-Sess-XID == resp.http.B-Sess-XID
	expect resp.http.C-Endpoint ~ ".?${v1_addr}.?:${v1_port}"
	expect resp.http.B-Endpoint ~ ".?${v1_addr}.?:${v1_port}"
	expect resp.http.C-Socket == "a0"
	expect resp.http.B-Socket == "a0"
} -run

vinyl v1 -stop

server s1 {
	rxreq
	txresp
	rxreq
	txresp
} -start

vinyl v2 -arg "-a foo=${tmpdir}/foo.sock -a bar=${tmpdir}/bar.sock" \
    -syntax 4.1 -vcl+backend {

	sub vcl_backend_response {
		set beresp.http.B-Endpoint = local.endpoint;
		set beresp.http.B-Socket = local.socket;
	}

	sub vcl_deliver {
		set resp.http.C-Endpoint = local.endpoint;
		set resp.http.C-Socket = local.socket;
	}
} -start

client c2 -connect "${tmpdir}/foo.sock" {
	txreq
	rxresp
	expect resp.status == 200
	expect resp.http.C-Endpoint == "${tmpdir}/foo.sock"
	expect resp.http.B-Endpoint == "${tmpdir}/foo.sock"
	expect resp.http.C-Socket == "foo"
	expect resp.http.B-Socket == "foo"
} -run

# The backend endpoint/socket may be either of the two possibilities,
# because the busyobj may point to the session started for the first
# fetch.
client c2 -connect "${tmpdir}/bar.sock" {
	txreq
	rxresp
	expect resp.status == 200
	expect resp.http.C-Endpoint == "${tmpdir}/bar.sock"
	expect resp.http.B-Endpoint ~ "^${tmpdir}/(bar|foo).sock$"
	expect resp.http.C-Socket == "bar"
	expect resp.http.B-Socket ~ "^(bar|foo)$"
} -run
