dropguardtest

package
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package dropguardtest runs a service's drop guard against a real database.

It lives apart from dropguard so that the library which decides things stays free of a dependency on the test runner. What a service needs to adopt the guard is one call: the harness replays that service's own migrations into a throwaway Postgres, pauses immediately before every drop, counts, and refuses on any disagreement with the service's dropguard.json.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Measure

func Measure(t *testing.T, opts Options) dropguard.Report

Measure does the work and REPORTS, without turning a refusal into a test failure.

It is separate from Run so that the guard can be proved to refuse: a proof injects a row, calls Measure, and asserts on the violations it gets back. Were the only entry point one that fails the test, the only way to check that the guard fails would be to watch it fail — which is not a check.

It still fails t for anything that means no measurement happened at all: a chain that will not replay, an unreadable manifest, a container that will not start. Those are not clean runs either.

func Run

func Run(t *testing.T, opts Options) dropguard.Report

Run replays the chain, measures every drop, and fails t on any refusal.

It also fails when the run measured fewer drops than the chain contains. A guard that reports no violations because it never got as far as asking is the exact shape of the problem this package was written for, so "how many did you look at" is asserted next to "what did you find".

Returns the report so a caller can assert something more specific.

Types

type Options

type Options struct {
	// Service is the service name, matched against the manifest's own field.
	Service string
	// FS is the service's embedded migration directory.
	FS fs.FS
	// ManifestPath is the path to dropguard.json, usually "dropguard.json"
	// relative to the migrations package under test.
	//
	// A chain that drops nothing owes no declarations, so an absent manifest is
	// accepted for such a chain and only for it — the same rule the repo-wide
	// static gate already applies to a service that has never dropped a table.
	ManifestPath string
	// DropsExpected is how many Up-section DROP TABLE statements the CALLER says
	// its chain holds. It is declared here rather than inferred, and that is the
	// whole of its value: it cannot move on its own, so a drop that appeared
	// without it moving is a drop nobody looked at.
	//
	// ZERO IS A LEGITIMATE VALUE, and saying so is the point. This used to be an
	// unstated assumption inside the harness — a chain with no drops was refused
	// outright, on the reasoning that the run would then assert nothing. That
	// reasoning was true of the population the harness was written for, where
	// every caller had drops, and it stopped being true when a service squashed
	// its chain into one primary migration: a consolidated chain is one STATE, and
	// a state has no history of drops to count. The refusal then fired on the
	// correct answer.
	//
	// What the run still asserts at zero is not nothing: the chain replays to head
	// against a real database, the manifest is reconciled against the migrations
	// (so a declaration that outlived its drop is still refused), and this number
	// still ratchets — add a drop and the count moves off zero and goes red.
	//
	// The undeclared zero value is safe in the only direction that matters: a
	// caller who forgets the field declares zero, and a chain that actually drops
	// something goes red rather than quiet.
	DropsExpected int
	// Seed, when set, runs each time the chain reaches a version at which
	// something is about to be counted, and is given the version actually
	// reached. It exists so the guard can be proved to fail on a table that is
	// not empty: the proof injects a row here, and the run must go red naming
	// that table. Nil in the gate itself.
	Seed func(ctx context.Context, db *sql.DB, reachedVersion int64) error
}

Options configures one measured run.

Jump to

Keyboard shortcuts

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