clamdtest

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package clamdtest provides a scriptable in-process fake clamd server for unit tests. It speaks just enough of the clamd wire protocol to exercise the client — z/n command framing and INSTREAM chunk decoding — over both unix and tcp listeners, and lets tests script arbitrary (mis)behavior.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildZip added in v0.2.2

func BuildZip(entries ...ZipEntry) []byte

BuildZip assembles a ZIP archive from the given entries, in memory.

It is hand-rolled because archive/zip cannot write encrypted entries and the zero-dependency policy (ADR-0003) rules out external zip libraries. Only what the integration tests need is implemented: store and raw-deflate methods, optional ZipCrypto encryption, no zip64. Round-trip through archive/zip (including keystream decryption of encrypted entries) is covered by unit tests; acceptance by unzip and 7z was verified manually during the 2026-07-30 clamd behavior verification.

BuildZip panics on an entry that is both encrypted and deflated; the harness never needs that combination.

func EICAR

func EICAR() []byte

EICAR returns the standard 68-byte EICAR anti-virus test payload. Every AV engine, ClamAV included, detects it by convention; the payload itself is inert.

func HeaderOnlyJPEG added in v0.2.2

func HeaderOnlyJPEG() []byte

HeaderOnlyJPEG returns a well-formed SOI/JFIF header followed by filler bytes with no scan data and no EOI marker. clamd flags it as Heuristics.Broken.Media.JPEG.* when AlertBrokenMedia is enabled.

func NestedZip added in v0.2.2

func NestedZip(depth int, name string, data []byte) []byte

NestedZip wraps data in depth layers of store-method zips. With depth above clamd's MaxRecursion the scan is flagged (AlertExceedsMax) or silently truncated (default config).

func TruncatedPNG added in v0.2.2

func TruncatedPNG() []byte

TruncatedPNG returns the first 60% of a valid PNG image: an intact signature and IHDR with the pixel stream cut mid-chunk. clamd flags it as Heuristics.Broken.Media.PNG.* when AlertBrokenMedia is enabled.

Types

type Fake

type Fake struct {
	// Addr is scheme-prefixed and can be passed directly to clamav.New.
	Addr string
	// contains filtered or unexported fields
}

Fake is an in-process fake clamd listening on a real socket.

func New

func New(t *testing.T, network string) *Fake

New starts a fake clamd on the given network ("unix" or "tcp") and registers cleanup with t. The default handler behaves like a healthy clamd that finds nothing.

func (*Fake) Close

func (f *Fake) Close()

Close shuts the fake down and waits for connection goroutines to finish. It is idempotent and also registered via t.Cleanup.

func (*Fake) SetHandler

func (f *Fake) SetHandler(h Handler)

SetHandler replaces the scripted handler.

func (*Fake) SetStreamLimit

func (f *Fake) SetStreamLimit(n int64)

SetStreamLimit makes the fake emulate clamd's StreamMaxLength: once an INSTREAM payload exceeds n bytes, it replies "INSTREAM size limit exceeded. ERROR" and closes the connection without draining the rest of the stream. 0 disables the emulation.

type Handler

type Handler func(req Request) Response

Handler produces the scripted response for one request.

func RespondWith

func RespondWith(raw string) Handler

RespondWith returns a handler that answers every request with the given raw bytes (remember the trailing NUL).

type Request

type Request struct {
	// Command is the command name with the z/n framing prefix stripped,
	// e.g. "PING" or "INSTREAM".
	Command string
	// Body is the decoded INSTREAM payload (nil for other commands).
	Body []byte
}

Request is one decoded client command.

type Response

type Response struct {
	// Data is written verbatim; include the trailing NUL yourself.
	Data []byte
	// Delay postpones writing Data (for timeout tests).
	Delay time.Duration
	// Hang, if set, never writes anything and holds the connection open
	// until the fake shuts down (for I/O timeout tests).
	Hang bool
}

Response scripts the fake's reaction to a Request. The connection is always closed after the response is handled, mimicking clamd ending the session after a non-IDSESSION command.

func DefaultHandler

func DefaultHandler(req Request) Response

DefaultHandler mimics a healthy clamd that finds nothing.

type ZipEntry added in v0.2.2

type ZipEntry struct {
	// Name is the entry's path inside the archive.
	Name string
	// Data is the uncompressed entry content.
	Data []byte
	// Password, when non-empty, encrypts the entry with the legacy PKWARE
	// "ZipCrypto" scheme (store method only). The scheme is
	// cryptographically broken and is used solely so clamd classifies the
	// entry as encrypted (Heuristics.Encrypted.Zip).
	Password string
	// Deflate compresses the entry (plaintext entries only). A deflated
	// entry is invisible to raw byte-level signature matching, so its
	// detection must go through clamd's archive module — which is exactly
	// what the archive-behavior integration tests need to exercise.
	Deflate bool
}

ZipEntry describes one file inside an archive built by BuildZip.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL