[master] ac5e880 Introduce the vmod vtc for varnishtest

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Mon Aug 14 16:41:10 CEST 2017


commit ac5e880a37f22d9458a4320ffe10ca1e18162926
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Thu Jul 6 14:42:47 2017 +0200

    Introduce the vmod vtc for varnishtest
    
    This is moving some of the generally useful functions of vmod debug to a
    new one that is installed for use out of the Varnish source tree. Things
    weren't just moved from one source file to another, some functions were
    sligthly renamed, and the behavior of `barrier_sync` was changed to
    adhere to the "universal fail" and no longer returns a boolean.
    
    While at it, I added missing __match_proto__ macros to vmod debug.
    
    Refs #2276
    Closes #2362

diff --git a/bin/varnishtest/tests/c00070.vtc b/bin/varnishtest/tests/c00070.vtc
index a3064d8..973af28 100644
--- a/bin/varnishtest/tests/c00070.vtc
+++ b/bin/varnishtest/tests/c00070.vtc
@@ -1,4 +1,4 @@
-varnishtest "Test workspace functions in vmod_debug"
+varnishtest "Test workspace functions in vmod_vtc"
 
 server s1 {
 	rxreq
@@ -9,20 +9,20 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 	sub vcl_backend_response {
-		set beresp.http.free_backend = debug.workspace_free(backend);
+		set beresp.http.free_backend = vtc.workspace_free(backend);
 	}
 
 	sub vcl_deliver {
-		set resp.http.free_session = debug.workspace_free(session);
-		set resp.http.free_thread = debug.workspace_free(thread);
+		set resp.http.free_session = vtc.workspace_free(session);
+		set resp.http.free_thread = vtc.workspace_free(thread);
 
-		set resp.http.overflowed = debug.workspace_overflowed(client);
-		debug.workspace_allocate(client, 2048);
+		set resp.http.overflowed = vtc.workspace_overflowed(client);
+		vtc.workspace_alloc(client, 2048);
 
 		if (req.url == "/bar") {
-			debug.workspace_overflow(client);
+			vtc.workspace_overflow(client);
 		}
 	}
 } -start
diff --git a/bin/varnishtest/tests/c00071.vtc b/bin/varnishtest/tests/c00071.vtc
index befa08d..fdeb2f8 100644
--- a/bin/varnishtest/tests/c00071.vtc
+++ b/bin/varnishtest/tests/c00071.vtc
@@ -12,9 +12,9 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 	sub vcl_deliver {
-		debug.workspace_allocate(client, -192);
+		vtc.workspace_alloc(client, -192);
 
 		if (req.url ~ "/bar") {
 			set resp.http.x-foo = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@@ -22,7 +22,7 @@ varnish v1 -vcl+backend {
 		else if (req.url ~ "/baz") {
 			set resp.http.x-foo = regsub(req.url, "baz", "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz");
 		}
-		set resp.http.x-of = debug.workspace_overflowed(client);
+		set resp.http.x-of = vtc.workspace_overflowed(client);
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/c00074.vtc b/bin/varnishtest/tests/c00074.vtc
index 61f2dec..1642e97 100644
--- a/bin/varnishtest/tests/c00074.vtc
+++ b/bin/varnishtest/tests/c00074.vtc
@@ -6,14 +6,14 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
 	import std;
+	import vtc;
 
 	sub vcl_recv {
-		set req.http.ws-free = debug.workspace_free(session);
-		debug.workspace_allocate(session, std.integer(req.http.ws-free, 0));
-		debug.workspace_snap(session);
-		debug.workspace_reset(session);
+		set req.http.ws-free = vtc.workspace_free(session);
+		vtc.workspace_alloc(session, std.integer(req.http.ws-free, 0));
+		vtc.workspace_snapshot(session);
+		vtc.workspace_reset(session);
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/c00078.vtc b/bin/varnishtest/tests/c00078.vtc
index 3a33888..613b971 100644
--- a/bin/varnishtest/tests/c00078.vtc
+++ b/bin/varnishtest/tests/c00078.vtc
@@ -10,14 +10,14 @@ varnish v1 \
     -arg "-ss2=malloc,1m" \
     -arg "-ss0=malloc,1m" \
     -vcl+backend {
-	import debug;
+	import vtc;
 	sub vcl_backend_response {
 		if (bereq.url == "/1") {
 			set beresp.storage_hint = "invalid";
 		} else if (bereq.url == "/2") {
 			set beresp.storage_hint = "s1";
 		} else if (bereq.url == "/6") {
-			set beresp.storage = debug.no_stevedore();
+			set beresp.storage = vtc.no_stevedore();
 		}
 		set beresp.http.storage = beresp.storage;
 	}
diff --git a/bin/varnishtest/tests/d00011.vtc b/bin/varnishtest/tests/d00011.vtc
index 21fd684..cecfbaf 100644
--- a/bin/varnishtest/tests/d00011.vtc
+++ b/bin/varnishtest/tests/d00011.vtc
@@ -13,6 +13,7 @@ server s2 {
 varnish v1 -vcl {
 	import std;
 	import debug;
+	import vtc;
 
 	backend dummy { .host = "${bad_backend}"; }
 
@@ -30,7 +31,7 @@ varnish v1 -vcl {
 	sub vcl_backend_fetch {
 		set bereq.backend = s1.backend();
 		# hot swap should happen while we sleep
-		debug.sleep(2s);
+		vtc.sleep(2s);
 		if (std.healthy(bereq.backend)) {
 			return(abandon);
 		} else {
diff --git a/bin/varnishtest/tests/d00013.vtc b/bin/varnishtest/tests/d00013.vtc
index a9b1826..1a5a610 100644
--- a/bin/varnishtest/tests/d00013.vtc
+++ b/bin/varnishtest/tests/d00013.vtc
@@ -13,6 +13,7 @@ server s2 {
 varnish v1 -vcl {
 	import std;
 	import debug;
+	import vtc;
 
 	backend dummy { .host = "${bad_backend}"; }
 
@@ -27,7 +28,7 @@ varnish v1 -vcl {
 		}
 		set req.backend_hint = s1.backend();
 		# hot swap should happen while we sleep
-		debug.sleep(2s);
+		vtc.sleep(2s);
 		if (std.healthy(req.backend_hint)) {
 			return(synth(800));
 		} else {
diff --git a/bin/varnishtest/tests/d00014.vtc b/bin/varnishtest/tests/d00014.vtc
index 3053db0..437cb95 100644
--- a/bin/varnishtest/tests/d00014.vtc
+++ b/bin/varnishtest/tests/d00014.vtc
@@ -3,10 +3,10 @@ varnishtest "Backend as a boolean expression"
 server s1 -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 
 	sub vcl_recv {
-		set req.backend_hint = debug.no_backend();
+		set req.backend_hint = vtc.no_backend();
 		if (!req.backend_hint) {
 			return (synth(404));
 		}
diff --git a/bin/varnishtest/tests/m00012.vtc b/bin/varnishtest/tests/m00012.vtc
index de3e835..276fa08 100644
--- a/bin/varnishtest/tests/m00012.vtc
+++ b/bin/varnishtest/tests/m00012.vtc
@@ -6,10 +6,10 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 
 	sub vcl_deliver {
-		set resp.http.foo = debug.blob2hex(debug.str2blob("gunk"));
+		set resp.http.foo = vtc.blob2hex(vtc.str2blob("gunk"));
 	}
 } -start
 
@@ -25,10 +25,10 @@ varnish v1 -errvcl {BLOBs can only be used as arguments to VMOD functions.} {
 
 	backend b1 {.host = "127.0.0.1";}
 
-	import debug;
+	import vtc;
 
 	sub vcl_deliver {
-		set resp.http.foo = debug.str2blob("gunk");
+		set resp.http.foo = vtc.str2blob("gunk");
 	}
 }
 
@@ -36,9 +36,9 @@ varnish v1 -errvcl {Wrong argument type.  Expected BLOB.  Got STRING.} {
 
 	backend b1 {.host = "127.0.0.1";}
 
-	import debug;
+	import vtc;
 
 	sub vcl_deliver {
-		set resp.http.foo = debug.blob2hex("gunk");
+		set resp.http.foo = vtc.blob2hex("gunk");
 	}
 }
diff --git a/bin/varnishtest/tests/m00024.vtc b/bin/varnishtest/tests/m00024.vtc
index 2124589..f7d9f7d 100644
--- a/bin/varnishtest/tests/m00024.vtc
+++ b/bin/varnishtest/tests/m00024.vtc
@@ -1,4 +1,4 @@
-varnishtest "Test debug.barrier_sync"
+varnishtest "Test vtc.barrier_sync"
 
 barrier b1 sock 2
 barrier b2 sock 2
@@ -9,18 +9,14 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 
 	sub vcl_recv {
-		if (!debug.barrier_sync("${b1_sock}")) {
-			return (synth(400));
-		}
+		vtc.barrier_sync("${b1_sock}");
 	}
 
 	sub vcl_backend_response {
-		if (!debug.barrier_sync("${b2_sock}")) {
-			return (abandon);
-		}
+		vtc.barrier_sync("${b2_sock}");
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/r01501.vtc b/bin/varnishtest/tests/r01501.vtc
index 38f220c..bcf1f4c 100644
--- a/bin/varnishtest/tests/r01501.vtc
+++ b/bin/varnishtest/tests/r01501.vtc
@@ -6,11 +6,10 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-
-	import debug;
+	import vtc;
 
 	sub vcl_recv {
-		set req.backend_hint = debug.no_backend();
+		set req.backend_hint = vtc.no_backend();
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/r01739.vtc b/bin/varnishtest/tests/r01739.vtc
index dbbd04d..c839542 100644
--- a/bin/varnishtest/tests/r01739.vtc
+++ b/bin/varnishtest/tests/r01739.vtc
@@ -6,12 +6,12 @@ server s1 {
 } -start
 
 
-varnish v1 \
- -vcl+backend {
-	import debug;
+varnish v1 -vcl+backend {
+	import vtc;
+
 	sub vcl_backend_response {
 		set beresp.do_gzip = true;
-		debug.workspace_allocate(backend, debug.workspace_free(backend) - 16);
+		vtc.workspace_alloc(backend, vtc.workspace_free(backend) - 16);
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/r01834.vtc b/bin/varnishtest/tests/r01834.vtc
index e5e1dbc..827105b 100644
--- a/bin/varnishtest/tests/r01834.vtc
+++ b/bin/varnishtest/tests/r01834.vtc
@@ -10,15 +10,15 @@ server s1 -repeat 64 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
 	import std;
+	import vtc;
 
 	sub vcl_recv {
 		return (pass);
 	}
 
 	sub vcl_backend_fetch {
-		debug.workspace_allocate(backend, -1 * std.integer(bereq.http.WS, 256));
+		vtc.workspace_alloc(backend, -1 * std.integer(bereq.http.WS, 256));
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/r01990.vtc b/bin/varnishtest/tests/r01990.vtc
index 7c72f0f..2b9dbbd 100644
--- a/bin/varnishtest/tests/r01990.vtc
+++ b/bin/varnishtest/tests/r01990.vtc
@@ -1,7 +1,7 @@
 varnishtest "workspace overflow with failed backend fetch"
 
 varnish v1 -vcl {
-	import debug;
+	import vtc;
 
 	backend default {
 		.host = "${bad_backend}";
@@ -10,8 +10,7 @@ varnish v1 -vcl {
 	sub vcl_backend_fetch {
 		# avoid LostHeader      b Host: %s
 		set bereq.http.Host = "127.0.0.1";
-		debug.workspace_allocate(backend,
-			debug.workspace_free(backend));
+		vtc.workspace_alloc(backend, vtc.workspace_free(backend));
 	}
 
 	sub vcl_backend_error {
diff --git a/bin/varnishtest/tests/r02233.vtc b/bin/varnishtest/tests/r02233.vtc
index f877f60..67fb20c 100644
--- a/bin/varnishtest/tests/r02233.vtc
+++ b/bin/varnishtest/tests/r02233.vtc
@@ -6,11 +6,11 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
 	import std;
+	import vtc;
 
 	sub vcl_recv {
-		debug.workspace_allocate(client, -92);
+		vtc.workspace_alloc(client, -92);
 		if (std.querysort(req.url) == req.url) {
 			std.log("querysort failed");
 		}
diff --git a/bin/varnishtest/tests/r02275.vtc b/bin/varnishtest/tests/r02275.vtc
index a5b2e27..0a56c16 100644
--- a/bin/varnishtest/tests/r02275.vtc
+++ b/bin/varnishtest/tests/r02275.vtc
@@ -12,17 +12,17 @@ server s1 -repeat 2 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 
 	sub vcl_deliver {
 		if (req.url == "/1") {
-			debug.workspace_allocate(client,
-			    -1 * (40 + debug.typesize("p") * 25));
+			vtc.workspace_alloc(client,
+			    -1 * (40 + vtc.typesize("p") * 25));
 		} else {
-			debug.workspace_allocate(client,
-			    -1 * (56 + debug.typesize("p") * 25));
+			vtc.workspace_alloc(client,
+			    -1 * (56 + vtc.typesize("p") * 25));
 		}
-		set resp.http.foo = debug.workspace_free(client);
+		set resp.http.foo = vtc.workspace_free(client);
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/r02339.vtc b/bin/varnishtest/tests/r02339.vtc
index d9e7fbe..b1d4477 100644
--- a/bin/varnishtest/tests/r02339.vtc
+++ b/bin/varnishtest/tests/r02339.vtc
@@ -7,6 +7,7 @@ server s1 -repeat 12 {
 
 varnish v1 -arg "-p thread_pools=1" -vcl+backend {
 	import debug;
+	import vtc;
 
 	sub vcl_recv {
 		if (req.url == "recv") { debug.purge(); }
@@ -38,7 +39,7 @@ varnish v1 -arg "-p thread_pools=1" -vcl+backend {
 	sub vcl_backend_fetch {
 		if (bereq.url == "fetch") { debug.purge(); }
 		if (bereq.url == "error") {
-			set bereq.backend = debug.no_backend();
+			set bereq.backend = vtc.no_backend();
 		}
 	}
 	sub vcl_backend_error {
diff --git a/bin/varnishtest/tests/t02004.vtc b/bin/varnishtest/tests/t02004.vtc
index b757660..58e8743 100644
--- a/bin/varnishtest/tests/t02004.vtc
+++ b/bin/varnishtest/tests/t02004.vtc
@@ -6,10 +6,10 @@ server s1 {
 } -start
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 
 	sub vcl_recv {
-		debug.panic("H2 panic");
+		vtc.panic("H2 panic");
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/t02007.vtc b/bin/varnishtest/tests/t02007.vtc
index e4d4699..b3fd521 100644
--- a/bin/varnishtest/tests/t02007.vtc
+++ b/bin/varnishtest/tests/t02007.vtc
@@ -21,18 +21,15 @@ server s1 {
 	expect req.url == /5
 } -start
 
-
 varnish v1 -cliok "param.set feature +http2"
 varnish v1 -cliok "param.set debug +syncvsl"
 varnish v1 -cliok "param.set debug +h2_nocheck"
 
 varnish v1 -vcl+backend {
-	import debug;
+	import vtc;
 	sub vcl_deliver {
 		if (req.url == "/1") {
-			if (!debug.barrier_sync("${b1_sock}")) {
-				return (synth(400));
-			}
+			vtc.barrier_sync("${b1_sock}");
 		}
 	}
 } -start
diff --git a/bin/varnishtest/tests/v00010.vtc b/bin/varnishtest/tests/v00010.vtc
index 43fb083..1c65a90 100644
--- a/bin/varnishtest/tests/v00010.vtc
+++ b/bin/varnishtest/tests/v00010.vtc
@@ -25,17 +25,16 @@ server s1 {
 } -start
 
 varnish v1 -arg "-smalloc,1m" -vcl+backend {
-
-	import debug;
+	import vtc;
 
 	sub vcl_backend_response {
 		if (beresp.http.panic == "fetch") {
-			debug.panic("Had Panic header: " + beresp.http.panic);
+			vtc.panic("Had Panic header: " + beresp.http.panic);
 		}
 	}
 	sub vcl_deliver {
 		if (resp.http.panic == "deliver") {
-			debug.panic("Had Panic header: " + resp.http.panic);
+			vtc.panic("Had Panic header: " + resp.http.panic);
 		}
 	}
 } -start
diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc
index bf31e4e..de031db 100644
--- a/bin/varnishtest/tests/v00020.vtc
+++ b/bin/varnishtest/tests/v00020.vtc
@@ -223,10 +223,10 @@ varnish v1 -errvcl {VCL sub's named 'vcl*' are reserved names.} {
 }
 
 varnish v1 -errvcl {Function returns VOID} {
-	import debug;
+	import vtc;
 	backend b { .host = "127.0.0.1"; }
 	sub vcl_recv {
-		set req.http.foo = debug.sleep(1m);
+		set req.http.foo = vtc.sleep(1m);
 	}
 }
 
@@ -253,10 +253,10 @@ varnish v1 -errvcl {Expected 'from path ...'} {
 }
 
 varnish v1 -errvcl {INT * BLOB not possible.} {
-	import debug;
+	import vtc;
 	backend b { .host = "127.0.0.1"; }
 	sub vcl_deliver {
-		set resp.status = 100 * debug.str2blob("a");
+		set resp.status = 100 * vtc.str2blob("a");
 	}
 }
 
diff --git a/bin/varnishtest/vmods.h b/bin/varnishtest/vmods.h
index f951b22..6f51d9e 100644
--- a/bin/varnishtest/vmods.h
+++ b/bin/varnishtest/vmods.h
@@ -30,3 +30,4 @@
 VTC_VMOD(std)
 VTC_VMOD(debug)
 VTC_VMOD(directors)
+VTC_VMOD(vtc)
diff --git a/configure.ac b/configure.ac
index a3adfb6..abcd5d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -729,6 +729,7 @@ AC_CONFIG_FILES([
     lib/libvmod_debug/Makefile
     lib/libvmod_std/Makefile
     lib/libvmod_directors/Makefile
+    lib/libvmod_vtc/Makefile
     man/Makefile
     varnishapi.pc
     varnishapi-uninstalled.pc
diff --git a/doc/changes.rst b/doc/changes.rst
index ef5938a..bed6ac5 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -25,13 +25,15 @@ VCL
 
 * Added ``bereq.is_bgfetch`` which is true for background fetches.
 
-C APIs (for vmod authors)
--------------------------
+C APIs (for vmod and utility authors)
+-------------------------------------
 
 * ``VSM_Name()`` returns the -i argument name, rather than the -n name.
 
 * ``VUT.name`` is gone, use ``VSM_Name(VUT.vsm)``
 
+* New vmod vtc for advanced varnishtest usage (#2276)
+
 ================================
 Varnish Cache 5.1.3 (2017-08-02)
 ================================
diff --git a/doc/sphinx/reference/varnishtest.rst b/doc/sphinx/reference/varnishtest.rst
index dd49963..bb18f6c 100644
--- a/doc/sphinx/reference/varnishtest.rst
+++ b/doc/sphinx/reference/varnishtest.rst
@@ -184,6 +184,7 @@ SEE ALSO
 * :ref:`varnishtop(1)`
 * :ref:`vcl(7)`
 * :ref:`vtc(7)`
+* :ref:`vmod_vtc(3)`
 
 HISTORY
 =======
diff --git a/doc/sphinx/reference/vtc.rst b/doc/sphinx/reference/vtc.rst
index d08ec22..876b809 100644
--- a/doc/sphinx/reference/vtc.rst
+++ b/doc/sphinx/reference/vtc.rst
@@ -66,6 +66,7 @@ SEE ALSO
 ========
 
 * :ref:`varnishtest(1)`
+* :ref:`vmod_vtc(3)`
 
 COPYRIGHT
 =========
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 871cbaf..dbb4ad9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,4 +7,5 @@ SUBDIRS = \
 	libvgz \
 	libvmod_debug \
 	libvmod_std \
-	libvmod_directors
+	libvmod_directors \
+	libvmod_vtc
diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c
index d8e2910..e76e08b 100644
--- a/lib/libvmod_debug/vmod_debug.c
+++ b/lib/libvmod_debug/vmod_debug.c
@@ -202,7 +202,7 @@ vmod_rot52(VRT_CTX, VCL_HTTP hp)
 	http_PrintfHeader(hp, "Encrypted: ROT52");
 }
 
-VCL_STRING
+VCL_STRING __match_proto__(td_debug_argtest)
 vmod_argtest(VRT_CTX, VCL_STRING one, VCL_REAL two, VCL_STRING three,
     VCL_STRING comma, VCL_INT four)
 {
@@ -212,7 +212,7 @@ vmod_argtest(VRT_CTX, VCL_STRING one, VCL_REAL two, VCL_STRING three,
 	return (WS_Copy(ctx->ws, buf, -1));
 }
 
-VCL_INT
+VCL_INT __match_proto__(td_debug_vre_limit)
 vmod_vre_limit(VRT_CTX)
 {
 	(void)ctx;
@@ -239,7 +239,7 @@ obj_cb(struct worker *wrk, void *priv, struct objcore *oc, unsigned event)
 	    (intmax_t)(uintptr_t)oc);
 }
 
-VCL_VOID __match_proto__()
+VCL_VOID __match_proto__(td_debug_register_obj_events)
 vmod_register_obj_events(VRT_CTX, struct vmod_priv *priv)
 {
 	struct priv_vcl *priv_vcl;
@@ -252,7 +252,7 @@ vmod_register_obj_events(VRT_CTX, struct vmod_priv *priv)
 	VSL(SLT_Debug, 0, "Subscribed to Object Events");
 }
 
-VCL_VOID __match_proto__()
+VCL_VOID __match_proto__(td_debug_fail)
 vmod_fail(VRT_CTX)
 {
 
@@ -487,7 +487,7 @@ vmod_workspace_overflow(VRT_CTX, VCL_ENUM which)
 	WS_MarkOverflow(ws);
 }
 
-void
+VCL_VOID __match_proto__(td_debug_vcl_release_delay)
 vmod_vcl_release_delay(VRT_CTX, VCL_DURATION delay)
 {
 
@@ -496,7 +496,7 @@ vmod_vcl_release_delay(VRT_CTX, VCL_DURATION delay)
 	vcl_release_delay = delay;
 }
 
-VCL_BOOL
+VCL_BOOL __match_proto__(td_debug_match_acl)
 vmod_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip)
 {
 
@@ -539,7 +539,7 @@ vmod_barrier_sync(VRT_CTX, VCL_STRING addr)
 	return (0);
 }
 
-VCL_VOID
+VCL_VOID __match_proto__(td_debug_test_probe)
 vmod_test_probe(VRT_CTX, VCL_PROBE probe, VCL_PROBE same)
 {
 
@@ -573,7 +573,7 @@ vmod_typesize(VRT_CTX, VCL_STRING s)
 	return ((VCL_INT)i);
 }
 
-VCL_VOID
+VCL_VOID __match_proto__(td_debug_purge)
 vmod_purge(VRT_CTX, double ttl, double grace, double keep)
 {
 
diff --git a/lib/libvmod_vtc/Makefile.am b/lib/libvmod_vtc/Makefile.am
new file mode 100644
index 0000000..98baa91
--- /dev/null
+++ b/lib/libvmod_vtc/Makefile.am
@@ -0,0 +1,41 @@
+#
+AM_LDFLAGS  = $(AM_LT_LDFLAGS)
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/bin/varnishd \
+	-I$(top_builddir)/include
+
+vmoddir = $(pkglibdir)/vmods
+vmod_srcdir = $(top_srcdir)/lib/libvmod_vtc
+vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
+vmodtoolargs =
+
+vmod_LTLIBRARIES = libvmod_vtc.la
+
+libvmod_vtc_la_CFLAGS = \
+	@SAN_CFLAGS@
+
+libvmod_vtc_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere \
+	@SAN_LDFLAGS@
+
+libvmod_vtc_la_SOURCES = \
+	vmod_vtc.c
+
+nodist_libvmod_vtc_la_SOURCES = \
+	vcc_if.c \
+	vcc_if.h
+
+# BUILT_SOURCES is only a hack and dependency tracking does not help for the first build
+$(libvmod_vtc_la_OBJECTS):vcc_if.h
+
+vcc_if.h vmod_vtc.rst vmod_vtc.man.rst: vcc_if.c
+
+vcc_if.c: $(vmodtool) $(vmod_srcdir)/vmod.vcc
+	@PYTHON@ $(vmodtool) $(vmodtoolargs) $(vmod_srcdir)/vmod.vcc
+
+EXTRA_DIST = vmod.vcc
+
+CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \
+	$(builddir)/vmod_vtc.rst \
+	$(builddir)/vmod_vtc.man.rst
diff --git a/lib/libvmod_vtc/vmod.vcc b/lib/libvmod_vtc/vmod.vcc
new file mode 100644
index 0000000..a932343
--- /dev/null
+++ b/lib/libvmod_vtc/vmod.vcc
@@ -0,0 +1,149 @@
+#
+# Copyright (c) 2017 Varnish Software AS
+# All rights reserved.
+#
+# Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+$Module vtc 3 Utility module for varnishtest
+
+DESCRIPTION
+===========
+
+The goal for this VMOD is to provide VCL users and VMOD authors means to
+test corner cases or reach certain conditions with varnishtest.
+
+$Function VOID barrier_sync(STRING addr, DURATION timeout = 0)
+
+When writing test cases, the most common pattern is to start a mock server
+instance, a Varnish instance, and spin up a mock client. Those entities run
+asynchronously, and others exist like background processes (``process``) or
+log readers (``logexpect``). While you can synchronize with individual
+entities and wait for their completion, you must use a barrier if you need
+to synchronize two or more entities, or wait until a certain point instead
+of completion.
+
+Not only is it possible to synchronize between test entities, with the
+``barrier_sync`` function you can even synchronize VCL code::
+
+    sub vcl_recv {
+        # wait for some barrier b1 to complete
+        vtc.barrier_sync("${b1_sock}");
+    }
+
+If the function fails to synchronize with the barrier for some reason, or if
+it reaches the optional timeout, it fails the VCL transaction.
+
+MISCELLANEOUS
+=============
+
+$Function BACKEND no_backend()
+
+Fails at backend selection.
+
+$Function STEVEDORE no_stevedore()
+
+Fails at storage selection.
+
+$Function VOID panic(STRING_LIST)
+
+It can be useful to crash the child process in order to test the robustness
+of a VMOD.
+
+$Function VOID sleep(DURATION)
+
+Block the current worker thread.
+
+WORKSPACES
+==========
+
+It can be useful to put a workspace in a given state when testing corner
+cases like resource exhaustion for a transaction, especially for VMOD
+development. All functions available allow to pick which workspace you
+need to tamper with, available values are ``client``, ``backend``, ``session``
+and ``thread``.
+
+$Function VOID workspace_alloc(ENUM { client, backend, session, thread },
+	INT size)
+
+Allocate and zero out memory from a workspace. A negative size will allocate
+as much as needed to leave that many bytes free. The actual allocation size
+may be higher to comply with memory alignment requirements of the CPU
+architecture. A failed allocation fails the transaction.
+
+$Function INT workspace_free(ENUM { client, backend, session, thread })
+
+Find how much unallocated space there is left in a workspace.
+
+$Function VOID workspace_snapshot(ENUM { client, backend, session, thread})
+
+Snapshot a workspace. Only one snapshot may be active at a time.
+
+$Function VOID workspace_reset(ENUM { client, backend, session, thread })
+
+Reset to the previous snapshot of a workspace, it must be the same workspace
+too.
+
+$Function BOOL workspace_overflowed(ENUM { client, backend, session, thread })
+
+Find whether the workspace overflow mark is set or not.
+
+$Function VOID workspace_overflow(ENUM { client, backend, session, thread })
+
+Mark a workspace as overflowed.
+
+$Function INT typesize(STRING)
+
+Returns the size in bytes of a collection of C-datatypes:
+
+* ``'p'``: pointer
+* ``'i'``: ``int``
+* ``'d'``: ``double``
+* ``'f'``: ``float``
+* ``'l'``: ``long``
+* ``'s'``: ``short``
+* ``'z'``: ``size_t``
+* ``'o'``: ``off_t``
+* ``'j'``: ``intmax_t``
+
+This can be useful for VMOD authors in conjunction with workspace operations.
+
+BLOBS
+=====
+
+For VMODs dealing with BLOB arguments or return values, the following functions
+offer convenience conversions to and from STRING.
+
+$Function BLOB str2blob(STRING src)
+
+Turn a string into a blob.
+
+$Function STRING blob2hex(BLOB src)
+
+Hexdump a blob.
+
+SEE ALSO
+========
+
+* :ref:`vtc(7)`
+* :ref:`vcl(7)`
diff --git a/lib/libvmod_vtc/vmod_vtc.c b/lib/libvmod_vtc/vmod_vtc.c
new file mode 100644
index 0000000..c4e18cf
--- /dev/null
+++ b/lib/libvmod_vtc/vmod_vtc.c
@@ -0,0 +1,262 @@
+/*-
+ * Copyright (c) 2012-2017 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at FreeBSD.org>
+ * Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "cache/cache.h"
+
+#include "vrt.h"
+#include "vtcp.h"
+#include "vtim.h"
+
+#include "vcc_if.h"
+
+VCL_VOID __match_proto__(td_vtc_barrier_sync)
+vmod_barrier_sync(VRT_CTX, VCL_STRING addr, VCL_DURATION tmo)
+{
+	const char *err;
+	char buf[32];
+	int sock, i;
+	ssize_t sz;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	AN(addr);
+	AN(*addr);
+	assert(tmo >= 0.0);
+
+	VSLb(ctx->vsl, SLT_Debug, "barrier_sync(\"%s\")", addr);
+	sock = VTCP_open(addr, NULL, 0., &err);
+	if (sock < 0) {
+		VRT_fail(ctx, "Barrier connection failed: %s", err);
+		return;
+	}
+
+	sz = VTCP_read(sock, buf, sizeof buf, tmo);
+	i = errno;
+	closefd(&sock);
+	if (sz < 0)
+		VRT_fail(ctx, "Barrier read failed: %s (errno=%d)",
+		    strerror(i), i);
+	if (sz > 0)
+		VRT_fail(ctx, "Barrier unexpected data (%zdB)", sz);
+}
+
+/*--------------------------------------------------------------------*/
+
+VCL_BACKEND __match_proto__(td_vtc_no_backend)
+vmod_no_backend(VRT_CTX)
+{
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	return (NULL);
+}
+
+VCL_STEVEDORE __match_proto__(td_vtc_no_stevedore)
+vmod_no_stevedore(VRT_CTX)
+{
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	return (NULL);
+}
+
+/*--------------------------------------------------------------------*/
+
+VCL_VOID __match_proto__(td_vtc_panic)
+vmod_panic(VRT_CTX, const char *str, ...)
+{
+	va_list ap;
+	const char *b;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	va_start(ap, str);
+	b = VRT_String(ctx->ws, "PANIC: ", str, ap);
+	va_end(ap);
+	VAS_Fail("VCL", "", 0, b, VAS_VCL);
+}
+
+/*--------------------------------------------------------------------*/
+
+VCL_VOID __match_proto__(td_vtc_sleep)
+vmod_sleep(VRT_CTX, VCL_DURATION t)
+{
+
+	CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
+	VTIM_sleep(t);
+}
+
+/*--------------------------------------------------------------------*/
+
+static uintptr_t vtc_ws_snapshot;
+
+static struct ws *
+vtc_ws_find(VRT_CTX, VCL_ENUM which)
+{
+
+	if (!strcmp(which, "client"))
+		return (ctx->ws);
+	if (!strcmp(which, "backend"))
+		return (ctx->bo->ws);
+	if (!strcmp(which, "session"))
+		return (ctx->req->sp->ws);
+	if (!strcmp(which, "thread"))
+		return (ctx->req->wrk->aws);
+
+	VRT_fail(ctx, "Unknown workspace: '%s'", which);
+	return (NULL);
+}
+
+VCL_VOID __match_proto__(td_vtc_workspace_alloc)
+vmod_workspace_alloc(VRT_CTX, VCL_ENUM which, VCL_INT size)
+{
+	struct ws *ws;
+	void *p;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	ws = vtc_ws_find(ctx, which);
+	WS_Assert(ws);
+
+	if (size < 0) {
+		size += WS_Reserve(ws, 0);
+		WS_Release(ws, 0);
+	}
+
+	p = WS_Alloc(ws, size);
+	if (p == NULL)
+		VRT_fail(ctx, "vtc.workspace_alloc");
+	else
+		memset(p, '\0', size);
+}
+
+VCL_INT __match_proto__(td_vtc_workspace_free)
+vmod_workspace_free(VRT_CTX, VCL_ENUM which)
+{
+	struct ws *ws;
+	unsigned u;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	ws = vtc_ws_find(ctx, which);
+	WS_Assert(ws);
+
+	u = WS_Reserve(ws, 0);
+	WS_Release(ws, 0);
+	return (u);
+}
+
+#define VTC_WS_OP(type, name, op)			\
+VCL_##type __match_proto__(td_vtc_workspace_##name)	\
+vmod_workspace_##name(VRT_CTX, VCL_ENUM which)		\
+{							\
+	struct ws *ws;					\
+							\
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);		\
+							\
+	ws = vtc_ws_find(ctx, which);			\
+	WS_Assert(ws);					\
+							\
+	op;						\
+}
+VTC_WS_OP(VOID, snapshot, vtc_ws_snapshot = WS_Snapshot(ws))
+VTC_WS_OP(VOID, reset, WS_Reset(ws, vtc_ws_snapshot))
+VTC_WS_OP(VOID, overflow, WS_MarkOverflow(ws))
+VTC_WS_OP(BOOL, overflowed, return (WS_Overflowed(ws)))
+#undef VTC_WS_OP
+
+/*--------------------------------------------------------------------*/
+
+VCL_INT __match_proto__(td_vtc_typesize)
+vmod_typesize(VRT_CTX, VCL_STRING s)
+{
+	VCL_INT i = 0;
+	const char *p;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	for (p = s; *p; p++) {
+		switch (*p) {
+#define VTC_TYPESIZE(c, t) case c: i += sizeof(t); break;
+		VTC_TYPESIZE('d', double)
+		VTC_TYPESIZE('f', float)
+		VTC_TYPESIZE('i', int)
+		VTC_TYPESIZE('j', intmax_t)
+		VTC_TYPESIZE('l', long)
+		VTC_TYPESIZE('o', off_t)
+		VTC_TYPESIZE('p', void *)
+		VTC_TYPESIZE('s', short)
+		VTC_TYPESIZE('z', size_t)
+#undef VTC_TYPESIZE
+		default:	return (-1);
+		}
+	}
+	return (i);
+}
+
+/*--------------------------------------------------------------------*/
+
+VCL_BLOB __match_proto__(td_vtc_str2blob)
+vmod_str2blob(VRT_CTX, VCL_STRING s)
+{
+	struct vmod_priv *p;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	p = WS_Alloc(ctx->ws, sizeof *p);
+	AN(p);
+	memset(p, 0, sizeof *p);
+	p->len = strlen(s);
+	p->priv = WS_Copy(ctx->ws, s, -1);
+	return (p);
+}
+
+VCL_STRING __match_proto__(td_vtc_blob2hex)
+vmod_blob2hex(VRT_CTX, VCL_BLOB b)
+{
+	char *s, *p;
+	uint8_t *q;
+	int i;
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	s = WS_Alloc(ctx->ws, b->len * 2 + 2);
+	AN(s);
+	p = s;
+	q = b->priv;
+	for (i = 0; i < b->len; i++) {
+		assert(snprintf(p, 3, "%02x", *q) == 2);
+		p += 2;
+		q += 1;
+	}
+	VRT_priv_fini(b);
+	return (s);
+}
diff --git a/man/Makefile.am b/man/Makefile.am
index d5332f6..fd7ee1a 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -16,7 +16,8 @@ dist_man_MANS = \
 	vtc.7 \
 	varnishtop.1 \
 	vmod_directors.3 \
-	vmod_std.3
+	vmod_std.3 \
+	vmod_vtc.3
 
 CLEANFILES = $(dist_man_MANS)
 
@@ -83,10 +84,13 @@ varnishhist.1: \
 	$(top_builddir)/doc/sphinx/include/varnishhist_synopsis.rst
 	${RST2MAN} $(RST2ANY_FLAGS) $(top_srcdir)/doc/sphinx/reference/varnishhist.rst $@
 
+vmod_directors.3: $(top_builddir)/lib/libvmod_directors/vmod_directors.man.rst
+	${RST2MAN} $(RST2ANY_FLAGS) $? $@
+
 vmod_std.3: $(top_builddir)/lib/libvmod_std/vmod_std.man.rst
 	${RST2MAN} $(RST2ANY_FLAGS) $? $@
 
-vmod_directors.3: $(top_builddir)/lib/libvmod_directors/vmod_directors.man.rst
+vmod_vtc.3: $(top_builddir)/lib/libvmod_vtc/vmod_vtc.man.rst
 	${RST2MAN} $(RST2ANY_FLAGS) $? $@
 
 .NOPATH: $(dist_man_MANS)



More information about the varnish-commit mailing list