This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
VTest2 is a standalone HTTP testing program, originally derived from Varnish's varnishtest. It's designed to test HTTP clients, servers, and proxies using a domain-specific scripting language (.vtc files). This is the second iteration that maintains better synchronization with Varnish-Cache while being usable independently.
make vtest # Build without Varnish support
make test # Build and run all tests
make clean # Remove build artifactsmake varnishtest VARNISH_SRC=/path/to/varnish-cacheThe build process generates two files that must exist before compilation:
src/teken_state.h- Generated fromsrc/sequencesusing awksrc/vtc_h2_dectbl.h- Generated fromsrc/tbl/vhp_huffman.husing Python
make update # Pull updates from Varnish-Cache repository
# Set VARNISHSRC env var to use local repo instead of cloning- lib/ - Shared utility library code from Varnish-Cache (vsb, vqueue, vtcp, etc.)
- src/ - Core VTest implementation
vtc_main.c- Entry point, test execution orchestration, parallel test runnervtc.c- Core test execution, macro expansion, command dispatchvtc_http.c/vtc_http.h- HTTP/1.1 client/server implementation with session operations abstractionvtc_http2.c- HTTP/2 supportvtc_tls.c- TLS/SSL support (OpenSSL-based)vtc_client.c- Client command implementationvtc_server.c- Server command implementationvtc_process.c- Process spawning and management with terminal emulationvtc_barrier.c- Synchronization primitives for testsvtc_logexp.c- Log expectation matching (conditional, Varnish-specific)vtc_varnish.c- Varnish-specific testing (conditional compilation)vtc_haproxy.c- HAProxy-specific testingbuiltin_cert.h- Default self-signed certificate (CN=example.com)vtc_asn_gentm.c- OpenSSL compatibility layer for older versionstbl/- Table-driven code generation (H2 frames, settings, errors, TLS alerts/protocols)
- tests/ - Test suite (
.vtcfiles) - tools/sync/ - Scripts for syncing code with Varnish-Cache
Commands are registered via cmds.h using X-macros:
- CMD_GLOBAL: Available everywhere (barrier, delay, shell, include)
- CMD_TOP: Top-level test commands (client, server, process, varnish, haproxy, etc.)
The extensible command system allows loading shared libraries via -E extension_shlib to add custom commands at runtime using add_cmd().
Test Execution Model:
Tests are executed in forked child processes with their own temporary directories. The main process (vtc_main.c) orchestrates parallel execution (configurable via -j), manages timeouts, and collects results via pipes.
Macro System: VTest has a powerful macro expansion system supporting:
- Static macros defined via
-D name=val - Dynamic macros defined in test scripts
- Function macros (e.g.,
${date},${string,repeat,N,text}) - Automatic macros for servers/clients (sNAME_addr, sNAME_port, sNAME_sock)
Session Abstraction:
HTTP clients and servers share common session handling code (vtc_sess.c, sess_process()) with pluggable connect/disconnect callbacks. This enables code reuse between client, server, and tunneling modes.
Session Operations Pattern:
VTest2 uses a session operations abstraction (struct sess_ops in vtc_http.h) that enables transparent switching between plain TCP and TLS connections. The struct http contains operation pointers (poll, read, write, close) that dispatch to either plain file descriptor operations (http_fd_so) or TLS operations (tlsconn_so). This allows all HTTP I/O code to remain unchanged whether using plain or encrypted connections.
Terminal Emulation:
Process commands include a full terminal emulator (teken.c) supporting VT220 escape sequences for testing interactive programs and screen output.
Tests are .vtc files that must start with vtest or varnishtest followed by a description:
vtest "Test description"
server s1 {
rxreq
txresp
} -start
client c1 -connect ${s1_sock} {
txreq
rxresp
expect resp.status == 200
} -run
vtest "Basic TLS test"
server s1 {
tls_config {
cert = "/path/to/cert.pem"
version = TLSv1.2 TLSv1.3
}
tls_handshake
rxreq
txresp -status 200
} -start
client c1 {
tls_config {
servername = "example.com"
verify_peer = false
}
tls_handshake
txreq -url "/"
rxresp
expect resp.status == 200
expect tls.version == "TLSv1.3"
} -run
- libpcre2-dev
- zlib
- libssl-dev (OpenSSL 1.0.x or later, 1.1.0+ recommended)
- Libraries typically available via Homebrew
- OpenSSL 3.x (via
brew install openssl@3)
Note: Current Makefile uses hardcoded paths for macOS. For portability, consider using pkg-config --cflags --libs libssl libcrypto.
- Linux: Uses
dlopen()by name for extensions. Primary development/testing platform. - macOS: Bound but non-listening sockets timeout instead of refusing, so bad_backend_fd is closed. TLS implementation compiles successfully but may encounter VTest2 runtime issues unrelated to TLS (file descriptor management in
VSUB_closefrom()). Recommend testing TLS features on Linux. - FreeBSD jails: localhost/127.0.0.1 becomes the jail's IP
Several features are conditionally compiled:
VTEST_WITH_VTC_VARNISH- Varnish integration (vtc_varnish.c)VTEST_WITH_VTC_LOGEXPECT- Log expectation matchingVTEST_WITH_VTC_VSM- Varnish Shared Memory support
VTest2 includes comprehensive TLS support ported from Varnish Cache Plus. See TLS-IMPL.md for detailed implementation documentation.
- TLS 1.0 through TLS 1.3 support (OpenSSL version dependent)
- Certificate loading and validation
- ALPN (Application-Layer Protocol Negotiation)
- Session resumption
- OCSP stapling
- Client certificate verification
- SNI (Server Name Indication)
- tls_config - Configure TLS settings (certificate, versions, ciphers, ALPN, etc.)
- tls_handshake - Perform TLS handshake and switch to encrypted I/O
Common (client & server):
cert = FILENAME- Load certificate/key bundle (PEM format)version = PROTO_MIN [PROTO_MAX]- Set TLS version range (SSLv3, TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3)cipher_list = CIPHER[:CIPHER...]- Set cipher list for TLS ≤ 1.2ciphersuites = CIPHER[:CIPHER...]- Set cipher suites for TLS 1.3alpn = PROTO [PROTO...]- Set ALPN protocol list (e.g., "h2 http/1.1")
Server-only:
client_vfy = none|optional|required- Client certificate verification modeclient_vfy_ca = FILENAME- CA bundle for client certificate verificationstaple = FILENAME- Provide OCSP staple response
Client-only:
servername = HOST- Set SNI hostnameverify_peer = true|false- Enable/disable certificate verificationsess_out = filename- Save TLS session for resumptionsess_in = filename- Resume TLS session from filecert_status = true|false- Request OCSP staple from server
After tls_handshake, these variables are available:
tls.version- Negotiated TLS version (e.g., "TLSv1.3")tls.cipher- Negotiated cipher suitetls.servername- SNI hostname (client)tls.alpn- Negotiated ALPN protocoltls.alert- Latest TLS alert messagetls.failed- "true" if handshake/I/O failedtls.cert[N].subject- Certificate CN (N=0 is peer cert)tls.cert[N].issuer- Certificate issuertls.cert[N].subject_alt_names- Subject Alternative Namestls.sess_reused- "true" if session was resumedtls.staple_requested- "true" if client requested OCSPtls.ocsp_cert_status- OCSP certificate statustls.ocsp_resp_status- OCSP response statustls.ocsp_verify- OCSP signature verification result
The TLS implementation uses a session operations abstraction pattern that allows seamless switching between plain TCP and TLS connections:
struct sess_opsdefines function pointers forpoll,read,write,closestruct httpcontains operation pointers that default to plain FD operations- After
tls_handshake, operations switch to TLS implementations - All HTTP I/O code remains unchanged - it transparently uses the correct operations
This design cleanly separates TLS concerns from HTTP protocol handling.
- Code in
lib/is synced from Varnish-Cache - don't modify directly - Extensions use
add_cmd(name, function, flags)to register new commands - Test names in
tests/follow patterna[0-9]{5}.vtc - Use
leave_tempoptions (-l,-L) to preserve test directories for debugging - The codebase uses Varnish's utility libraries: miniobj for object checking, vsb for string buffers, vqueue for linked lists
- TLS support requires OpenSSL; version detection happens at compile-time via
OPENSSL_VERSION_NUMBER - Default self-signed certificate (CN=example.com) is embedded in
builtin_cert.hfor testing without providing certificates