inv

package module
v0.0.0-...-779a2da Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2024 License: MIT Imports: 4 Imported by: 1

README

inv

Runtime assertions for your invariants.

Why?

This package is inspired by the prior art around runtime assertions in other languages. It tries to bridge the gap between the Go philosophy of proper handling by not encouraging the use of panics around assertions and by capturing useful, contextual information about invariants at key points of a program.

Some references:

Installation

go get -u github.com/disintegrator/inv

Quick start

Add this import line to your Go source files:

import "github.com/disintegrator/inv"

In any functions where you have some invariants that might constitute preconditions, postconditions or otherwise, check them like so:

func DoSomething(x int, species string, data []byte) error {
	if err := inv.Check(
		"do-something-inputs",
		"non-zero-operand", x != 0,
		"species-is-cat", species == "cat",
		"non-empty-data", len(data) > 0,
	); err != nil {
		return err
	}

	return nil
}

func main() {
	fmt.Println(DoSomething(0, "nope.txt", "dog", nil))
}

When invariants are not met, the returned error will summarize the failures:

/tmp/sandbox/prog.go:12: invariant mismatch: do something inputs: non-zero operand
/tmp/sandbox/prog.go:12: invariant mismatch: do something inputs: species is cat
/tmp/sandbox/prog.go:12: invariant mismatch: do something inputs: non-empty data
/tmp/sandbox/prog.go:12: invariant mismatch: do something inputs: path can be opened: open nope.txt: no such file or directory

Panics

There are two variations of the Check function that trigger panics based on go build tags.

inv.Require will always panic if any of the invariants are not met in a group:

func DoSomething(x int, species string, data []byte) error {
	inv.Require(
		"do-something-inputs",
		"non-zero-operand", x != 0,
		"species-is-cat", species == "cat",
		"non-empty-data", len(data) > 0,
	)

	// ... rest of function ...
}

This is the equivalent of runtime assertions in other languages.

inv.Debug is a variation that has no effect in regular builds but it can be enabled by setting the inv.debug build tag:

go build -tags inv.debug [build flags]
func DoSomething(x int, species string, data []byte) error {
	inv.Debug(
		"do-something-inputs",
		"non-zero-operand", x != 0,
		"species-is-cat", species == "cat",
		"non-empty-data", len(data) > 0,
	)

	// ... rest of function ...
}

This is the equivalent of debug assertions in other languages.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Check

func Check(group string, pairs ...any) error

Check checks a set of invariants and returns an error if any of them fail. Each invariant is passed as a pair: the name of the invariant as a string and a value that may be a boolean or error or function that return either of these types. If any value is false or a non-nil error across the pairs, then an error is returned with all the unmet invariants. Since this function checks multiple invariants, a group name is used to relate these checks together.

func Debug

func Debug(group string, pairs ...any)

Debug tests a set of invariants and panics if any of them fail. This function is only available in "debug" builds when can be enabled by setting any of the following build tags: `inv.debug`.

func Require

func Require(group string, pairs ...any)

Require tests a set of invariants and panics if any of them fail.

Types

type CheckError

type CheckError struct {
	// ID is the name of the invariant that was not met.
	ID string
	// Group is a label that relates this error to others.
	Group string
	// The location in code where the invariant was checked.
	Caller string
	// Cause is the underlying error that caused the invariant check to fail.
	Cause error
}

CheckError represents an invariant mismatch. If the invariant failed because of a non-nil error then Cause will be set.

func (*CheckError) Error

func (ae *CheckError) Error() string

Error returns a string representation of the invariant error.

func (*CheckError) Unwrap

func (ae *CheckError) Unwrap() error

Unwrap returns the underlying error that caused the invariant check to fail.

type InvariantError

type InvariantError struct {
	Failures []*CheckError
}

InvariantError captures a group of invariant check failures.

func (*InvariantError) Error

func (e *InvariantError) Error() string

Jump to

Keyboard shortcuts

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