VMOD_VTC(3)

✨ vmod_vtc β€” bestie's guide to the utility module for varnishtest ✨

okay so. hi. welcome to vmod_vtc, the utility module for varnishtest. she's a whole vibe. πŸ’…


🌸 SYNOPSIS 🌸

import vtc [as name] [from "path"]

VOID barrier_sync(STRING addr, DURATION timeout)

BACKEND no_backend()

STEVEDORE no_stevedore()

IP no_ip()

VOID panic(STRING)

VOID sleep(DURATION)

VOID workspace_alloc(ENUM, INT size)

BYTES workspace_reserve(ENUM, INT size)

INT workspace_free(ENUM)

VOID workspace_snapshot(ENUM)

VOID workspace_reset(ENUM)

BOOL workspace_overflowed(ENUM)

VOID workspace_overflow(ENUM)

BLOB workspace_dump(ENUM, ENUM, BYTES off, BYTES len)

INT typesize(STRING)

BLOB proxy_header(ENUM version, IP client, IP server, STRING authority)

VOID vsl(INT vxid, STRING tag, ENUM side, STRING s)

VOID vsl_replay(STRING s)

πŸ’– DESCRIPTION πŸ’–

okay so the whole goal for this VMOD? it's giving "let me help you break things on purpose." πŸŽ€ It gives VCL users and VMOD authors the means to test corner cases or reach certain conditions with varnishtest. no cap, that's literally the mission statement.

🫢 VOID barrier_sync(STRING addr, DURATION timeout=0)

so when you're writing test cases, the most common pattern is: 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). you can synchronize with individual entities and wait for their completion, but bestie β€” you must use a barrier if you need to synchronize two or more entities, or wait until a certain point instead of completion. that's the whole point.

and it's not just between test entities either πŸ‘€ β€” 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. periodt.


🌈 MISCELLANEOUS 🌈

πŸŽ€ BACKEND no_backend()

Fails at backend selection. that's it. that's the function.

πŸŽ€ STEVEDORE no_stevedore()

Fails at storage selection. iconic behaviour honestly.

πŸŽ€ IP no_ip()

Returns a null IP address, not even a bogo_ip. the absolute bare minimum. πŸ’€

πŸŽ€ VOID panic(STRING)

it can be useful to crash the child process in order to test the robustness of a VMOD. yes really, we're doing this on purpose πŸ™ˆ

πŸŽ€ VOID sleep(DURATION)

Block the current worker thread. she's napping. let her nap. 😴


πŸ¦‹ WORKSPACES πŸ¦‹

okay so 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 the functions available let you pick which workspace you need to tamper with, and the available values are client, backend, session and thread. ✨

πŸ’œ VOID workspace_alloc(ENUM, INT size)

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. so like, be normal about it.

πŸ’œ BYTES workspace_reserve(ENUM, INT size)

BYTES workspace_reserve(
   ENUM {client, backend, session, thread},
   INT size
)

Attempt to reserve size bytes, zero out that memory and release the reservation right away. return the size of the reservation. 🫢

See vtc.workspace_alloc() for semantics of the size argument. same rules, bestie.

πŸ’œ INT workspace_free(ENUM {client, backend, session, thread})

Find how much unallocated space there is left in a workspace. a little check-in on your workspace's emotional availability.

πŸ’œ VOID workspace_snapshot(ENUM)

VOID workspace_snapshot(ENUM {client, backend, session, thread})

Snapshot a workspace. ⚠️ only one snapshot may be active at a time and each VCL can save only one snapshot, so concurrent tasks requiring snapshots are not supported. no sharing, she's monogamous.

πŸ’œ VOID workspace_reset(ENUM)

VOID workspace_reset(ENUM {client, backend, session, thread})

Reset to the previous snapshot of a workspace β€” and it must be the same workspace too. don't be messy about it.

πŸ’œ BOOL workspace_overflowed(ENUM)

BOOL workspace_overflowed(ENUM {client, backend, session, thread})

Find whether the workspace overflow mark is set or not. vibe check on the overflow mark. πŸŽ€

πŸ’œ VOID workspace_overflow(ENUM)

VOID workspace_overflow(ENUM {client, backend, session, thread})

Mark a workspace as overflowed. just straight up lie to it. love that for us.

πŸ’œ BLOB workspace_dump(ENUM, ENUM, BYTES off, BYTES len)

BLOB workspace_dump(
   ENUM {client, backend, session, thread},
   ENUM {s, f, r},
   BYTES off=0,
   BYTES len=64
)

Return data from a workspace's s, f, or r pointer as a blob. data is copied onto the primary workspace to avoid it being subsequently overwritten. 🫢

the maximum len is 1KB. do not test her.

πŸ’œ 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. iykyk. πŸ”₯

πŸ’œ BLOB proxy_header(ENUM version, IP client, IP server, STRING authority)

BLOB proxy_header(
   ENUM {v1, v2} version,
   IP client,
   IP server,
   STRING authority=0
)

Format a proxy header of the given version v1 or v2 and addresses (the VCL IP type also contains the port number). πŸ‘‘

optionally also send an authority TLV with version v2 (ignored for version v1).

candidate for moving into vmod_proxy, but there were concerns about the interface design. so she stays here for now. πŸ™ˆ


⭐ VSL ⭐

these functions allow you to generate arbitrary log entries to test the Varnish Shared Log (VSL) implementation and readers like varnishlog. let's get messy with the logs.

πŸ’… VOID vsl(INT vxid, STRING tag, ENUM {c, b} side, STRING s)

Call VSLs() with the given parameters.

the argument order is chosen to match VSL output. no notes.

a VCL error is triggered if tag cannot be resolved at runtime or if vxid is out of bounds. ⚠️ watch those.

πŸ’… VOID vsl_replay(STRING s)

Replay literal log lines. 🎬

the parser accepts the output generated by varnishlog -g raw and varnishtest log vsl| lines.

unparseable lines are silently ignored. she's not going to argue with you.


🌟 SEE ALSO 🌟


Copyright (c) 2017 Varnish Software AS
All rights reserved.

Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>

SPDX-License-Identifier: BSD-2-Clause

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.

NB: Default to strict $ABI handling, so that path is tested in vmodtool.py

and that's the whole page bestie πŸ’– this one came from the Library Functions Manual, version VMOD_VTC(3), and she was born on... okay she doesn't say a date but she's very much a VMOD_VTC(3) girlie, top and bottom of the page, same energy. slay. go break something on purpose. πŸ¦‹βœ¨

πŸ“¦ where this page comes from