specta#

import "github.com/james-w/specta"

Package specta provides deterministic, concurrency-safe generators of primitive values for use in tests, plus spec-first factory utilities.

Index#

func AssertThat#

func AssertThat[T any](t TestingT, actual T, matcher Matcher[T])

AssertThat checks if actual matches the given matcher, failing the test if not.

func BuildMatcherStructDiff#

func BuildMatcherStructDiff(typeName string, fieldValues map[string]any, fieldResults map[string]*MatchResult) string

BuildMatcherStructDiff creates a structured diff output for generated matchers. It shows matched (✓), failed (✗), and unchecked (~) fields with proper indentation.

func DeterministicUUIDFromInt#

func DeterministicUUIDFromInt(i uint64) uuid.UUID

func Draw#

func Draw[V any](t *T, gen Gen[V], label string) V

Draw draws a labeled value from a generator and automatically tracks it for error reporting. Using labels improves error messages by showing variable names in failures.

Example:

xs := specta.Draw(t, specta.Slice(specta.Int().Range(0, 100)), "xs")

The generated value will automatically appear in error messages when the property fails.

Error handling: - Programming errors (invalid constraints, frozen data) panic with clear messages - Filtering errors (overrun during replay, assumption failures) trigger skipTest to skip the iteration

func Property#

func Property(t TestingT, check func(*T), opts ...PropertyOption)

Property runs a property-based test. It executes the check function multiple times with randomly generated inputs. If a failure is detected, it attempts to shrink the input to a minimal failing case.

Example:

Property(t, func(t *specta.T) {
    x := Int().Draw(t, "x")
    y := Int().Draw(t, "y")
    AssertThat(t, x+y, Equal(y+x))
})

func RequireThat#

func RequireThat[T any](t TestingT, actual T, matcher Matcher[T])

RequireThat checks if actual matches the given matcher, stopping the test immediately if not. Unlike AssertThat which continues after failures, RequireThat calls t.Fatalf() to halt execution. This is useful for preconditions where subsequent code would panic or produce misleading errors.

Example:

// Guard condition - user must not be nil for subsequent assertions
RequireThat(t, user, NotNil())
AssertThat(t, user.Name, Equal("Alice"))  // Safe - user is guaranteed non-nil

type BuildWithSpec#

BuildWithSpec constructs T from Source plus the collected spec S.

type BuildWithSpec[T any, S any] func(s Source, spec S) T

type ChoiceGenerator#

ChoiceGenerator provides fluent API for choosing between alternative generators

type ChoiceGenerator[T any] struct {
    // contains filtered or unexported fields
}

func Choice#

func Choice[T any](gens ...Gen[T]) *ChoiceGenerator[T]

Choice creates a generator that chooses uniformly from the given alternatives. Earlier alternatives are preferred during shrinking.

Example:

gen := specta.Choice(
    specta.Int().Range(1, 10),
    specta.Int().Range(100, 200),
)

func (*ChoiceGenerator[T]) Draw#

func (g *ChoiceGenerator[T]) Draw(d conjecture.DataSource) (T, error)

Draw implements Gen[T]

func (*ChoiceGenerator[T]) Filter#

func (g *ChoiceGenerator[T]) Filter(pred func(T) bool) Gen[T]

Filter returns a generator that only produces values satisfying the predicate

func (*ChoiceGenerator[T]) Or#

func (g *ChoiceGenerator[T]) Or(gen Gen[T]) *ChoiceGenerator[T]

Or adds another alternative with equal weight

func (*ChoiceGenerator[T]) OrWeighted#

func (g *ChoiceGenerator[T]) OrWeighted(gen Gen[T], weight int) *ChoiceGenerator[T]

OrWeighted adds an alternative with a specific weight. The first call to OrWeighted converts to weighted mode (existing alternatives get weight 1).

Example:

// 90% small numbers, 10% large numbers
gen := specta.Choice(specta.Int().Range(1, 10)).
    OrWeighted(specta.Int().Range(100, 200), 1)

func (*ChoiceGenerator[T]) String#

func (g *ChoiceGenerator[T]) String() string

String implements Gen[T]

type DataSource#

DataSource is re-exported from conjecture for user convenience. Users can write custom generators without importing conjecture package.

type DataSource = conjecture.DataSource

type Gen#

Gen is an alias for conjecture.Gen for convenience

type Gen[T any] = conjecture.Gen[T]

func Bool#

func Bool() Gen[bool]

Bool creates a boolean generator

func Build#

func Build[T any](label string, constructor func(d DataSource) (T, error)) Gen[T]

Build creates a new generator from a constructor function. Re-exported from conjecture for user convenience.

func Bytes#

func Bytes() Gen[[]byte]

Bytes creates a []byte generator

func BytesLen#

func BytesLen(minLen, maxLen int) Gen[[]byte]

BytesLen creates a []byte generator with specific length

func Duration#

func Duration() Gen[time.Duration]

Duration creates a time.Duration generator

func Email#

func Email() Gen[string]

Email returns a generator for email addresses

func Float64#

func Float64(min, max float64) Gen[float64]

Float64 creates a float64 generator for [min, max]

func FromSpecGen#

func FromSpecGen[T any, S any](build BuildWithSpec[T, S], newSpec func() S, opts ...Opt[S]) Gen[T]

FromSpecGen creates a Gen[T] from a BuildWithSpec function and spec options. This is used for generating nested custom types.

func Just#

func Just[T any](value T) Gen[T]

Just creates a generator that always returns the same literal value. Re-exported from conjecture for user convenience.

func Map#

func Map[T, U any](gen Gen[T], fn func(T) U) Gen[U]

Map transforms a generator’s output using a mapping function. Re-exported from conjecture for user convenience.

func Optional#

func Optional[T any](gen Gen[T], presentProbability ...float64) Gen[*T]

Optional returns a generator that produces either a value or nil (pointer with optional probability). Returns a pointer: nil for no value, *T for a value.

By default, generates present values 80% of the time (matching conjecture.Optional). Pass a custom probability to override:

specta.Optional(gen)       // 80% present
specta.Optional(gen, 0.5)  // 50% present
specta.Optional(gen, 0.2)  // 20% present (rare)
specta.Optional(gen, 0.95) // 95% present (common)

func Pair#

func Pair[A, B any](ga Gen[A], gb Gen[B]) Gen[struct {
    A   A
    B   B
}]

Pair generates a tuple of two values. Returns a struct with fields A and B.

Example:

coords := specta.Pair(
    specta.Float64(-180, 180),  // longitude
    specta.Float64(-90, 90),    // latitude
)
pair := specta.Draw(pt, coords, "coords")
lon := pair.A  // float64
lat := pair.B  // float64

func PtrOfGen#

func PtrOfGen[T any](gen Gen[T]) Gen[*T]

PtrOfGen creates a Gen[*T] from a Gen[T]. This is used for generating pointers to custom types.

func Time#

func Time() Gen[time.Time]

Time creates a time.Time generator

func Triple#

func Triple[A, B, C any](ga Gen[A], gb Gen[B], gc Gen[C]) Gen[struct {
    A   A
    B   B
    C   C
}]

Triple generates a tuple of three values. Returns a struct with fields A, B, and C.

Example:

coords3d := specta.Triple(
    specta.Float64(-180, 180),  // longitude
    specta.Float64(-90, 90),    // latitude
    specta.Float64(0, 10000),   // altitude
)

func URL#

func URL() Gen[string]

URL returns a generator for URLs

func UUID#

func UUID() Gen[string]

UUID creates a UUID string generator

func UUIDString#

func UUIDString() Gen[string]

UUIDString returns a generator for UUID strings (alias for UUID)

type Generator#

Generator is an alias for Gen[T] - used in generated code for convenience

type Generator[T any] = Gen[T]

type IntGenerator#

IntGenerator provides a fluent API for building integer generators

type IntGenerator struct {
    // contains filtered or unexported fields
}

func Int#

func Int() *IntGenerator

Int creates an integer generator with optional constraints

func (*IntGenerator) Draw#

func (g *IntGenerator) Draw(d conjecture.DataSource) (int64, error)

Draw implements Gen[int64]

func (*IntGenerator) Filter#

func (g *IntGenerator) Filter(pred func(int64) bool) Gen[int64]

Filter returns a generator that only produces integers satisfying the predicate

func (*IntGenerator) Max#

func (g *IntGenerator) Max(max int64) *IntGenerator

Max sets the maximum value (inclusive)

func (*IntGenerator) Min#

func (g *IntGenerator) Min(min int64) *IntGenerator

Min sets the minimum value (inclusive)

func (*IntGenerator) Negative#

func (g *IntGenerator) Negative() *IntGenerator

Negative constrains to negative integers (< 0)

func (*IntGenerator) NonNegative#

func (g *IntGenerator) NonNegative() *IntGenerator

NonNegative constrains to non-negative integers (>= 0)

func (*IntGenerator) Positive#

func (g *IntGenerator) Positive() *IntGenerator

Positive constrains to positive integers (> 0)

func (*IntGenerator) Range#

func (g *IntGenerator) Range(min, max int64) *IntGenerator

Range constrains the integer to [min, max]

func (*IntGenerator) String#

func (g *IntGenerator) String() string

String implements Gen[int64]

type Interval#

Interval represents a contiguous range of bytes drawn from the random source. Intervals are used by the shrinker to understand the structure of generated values and perform intelligent minimization (e.g., deleting entire values, reordering).

type Interval struct {
    // Start is the byte offset where this interval begins in the data stream
    Start int
    // End is the byte offset where this interval ends (exclusive)
    End int
    // Label is a human-readable description of what this interval represents
    // (e.g., "x", "list_length", "element_0")
    Label string
}

type MapGenerator#

MapGenerator provides fluent API for map generation

type MapGenerator[K comparable, V any] struct {
    // contains filtered or unexported fields
}

func MapOf#

func MapOf[K comparable, V any](keyGen Gen[K], valueGen Gen[V]) *MapGenerator[K, V]

MapOf creates a map generator from key and value generators.

func (*MapGenerator[K, V]) Draw#

func (g *MapGenerator[K, V]) Draw(d conjecture.DataSource) (map[K]V, error)

Draw implements Gen[map[K]V]

func (*MapGenerator[K, V]) Filter#

func (g *MapGenerator[K, V]) Filter(pred func(map[K]V) bool) Gen[map[K]V]

Filter returns a generator that only produces maps satisfying the predicate

func (*MapGenerator[K, V]) MaxLen#

func (g *MapGenerator[K, V]) MaxLen(n int) *MapGenerator[K, V]

MaxLen sets maximum map size

func (*MapGenerator[K, V]) MinLen#

func (g *MapGenerator[K, V]) MinLen(n int) *MapGenerator[K, V]

MinLen sets minimum map size

func (*MapGenerator[K, V]) NonEmpty#

func (g *MapGenerator[K, V]) NonEmpty() *MapGenerator[K, V]

NonEmpty ensures map has at least one entry

func (*MapGenerator[K, V]) String#

func (g *MapGenerator[K, V]) String() string

String implements Gen[map[K]V]

type MatchResult#

MatchResult represents the result of a match operation.

type MatchResult struct {
    Matched  bool     // Whether the match succeeded
    Message  string   // Human-readable description of the failure
    Details  []string // Additional details about what didn't match
    Expected any      // Expected value (optional, for better error messages)
    Actual   any      // Actual value (optional, for better error messages)
    Path     string   // Field path for nested failures (e.g., "User.Address.City")
}

type Matcher#

Matcher defines an interface for matching values of type T.

type Matcher[T any] interface {
    Matches(actual T) MatchResult
}

func After#

func After(expected time.Time) Matcher[time.Time]

After creates a matcher that checks if a time is after the expected time.

func AllOf#

func AllOf[T any](matchers ...Matcher[T]) Matcher[T]

AllOf creates a matcher that requires all sub-matchers to match.

func Any#

func Any[T any](matcher Matcher[T]) Matcher[[]T]

Any creates a matcher that checks if at least one element in a slice matches the given matcher.

func AnyOf#

func AnyOf[T any](matchers ...Matcher[T]) Matcher[T]

AnyOf creates a matcher that requires at least one sub-matcher to match.

func Before#

func Before(expected time.Time) Matcher[time.Time]

Before creates a matcher that checks if a time is before the expected time.

func Between#

func Between(start, end time.Time) Matcher[time.Time]

Between creates a matcher that checks if a time is between start and end (inclusive).

func Contains#

func Contains(substr string) Matcher[string]

Contains checks if a string contains a substring.

func ContainsAllElements#

func ContainsAllElements[T comparable](items ...T) Matcher[[]T]

ContainsAllElements creates a matcher that checks if a slice contains all expected items.

func ContainsAnyElement#

func ContainsAnyElement[T comparable](items ...T) Matcher[[]T]

ContainsAnyElement creates a matcher that checks if a slice contains at least one of the expected items.

func ContainsElement#

func ContainsElement[T comparable](item T) Matcher[[]T]

ContainsElement creates a matcher that checks if a slice contains the expected item.

func DeepEqual#

func DeepEqual[T any](expected T) Matcher[T]

DeepEqual creates a matcher that uses reflect.DeepEqual for comparison. This works with any type, including slices, maps, and other non-comparable types.

func Equal#

func Equal[T comparable](expected T) Matcher[T]

Equal creates a matcher that checks for exact equality.

func ErrorAs#

func ErrorAs[T error](target *T) Matcher[error]

ErrorAs creates a matcher that checks if an error can be assigned to the target type using errors.As. The target parameter must be a pointer to an error type.

func ErrorContains#

func ErrorContains(substr string) Matcher[error]

ErrorContains creates a matcher that checks if an error’s message contains the expected substring. Returns false if the error is nil.

func ErrorIs#

func ErrorIs(target error) Matcher[error]

ErrorIs creates a matcher that checks if an error matches the target error using errors.Is. This checks the error chain, not just equality.

func Every#

func Every[T any](matcher Matcher[T]) Matcher[[]T]

Every creates a matcher that checks if all elements in a slice match the given matcher.

func Field#

func Field[T any, V any](name string, extractor func(T) V, matcher Matcher[V]) Matcher[T]

Field creates a matcher that extracts a value from T using an extractor function, then applies a matcher to the extracted value. This is useful for: - Matching on computed/derived values - Matching on values from getter methods - Matching on unexported fields (via getters)

Example:

Field("balance * 2", func(acc BankAccount) int {
    return acc.GetBalance() * 2
}, Equal(2000))

func GreaterThan#

func GreaterThan[T interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]

GreaterThan creates a matcher for numeric types.

func GreaterThanOrEqual#

func GreaterThanOrEqual[T interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]

GreaterThanOrEqual creates a matcher for numeric types.

func HasEntry#

func HasEntry[K comparable, V comparable](key K, value V) Matcher[map[K]V]

HasEntry creates a matcher that checks if a map contains the specified key-value pair.

func HasKey#

func HasKey[K comparable, V any](key K) Matcher[map[K]V]

HasKey creates a matcher that checks if a map contains the specified key.

func HasPrefix#

func HasPrefix(prefix string) Matcher[string]

HasPrefix checks if a string has a given prefix.

func HasSize#

func HasSize[T any](expectedSize int) Matcher[[]T]

HasSize creates a matcher that checks if a slice has exactly the expected size.

func HasSuffix#

func HasSuffix(suffix string) Matcher[string]

HasSuffix checks if a string has a given suffix.

func HasValue#

func HasValue[K comparable, V comparable](value V) Matcher[map[K]V]

HasValue creates a matcher that checks if a map contains the specified value.

func Is#

func Is[T comparable](expected T) Matcher[T]

Is is an alias for Equal for more readable assertions.

func IsEmpty#

func IsEmpty[T any]() Matcher[[]T]

IsEmpty creates a matcher that checks if a slice is empty.

func IsError#

func IsError() Matcher[error]

IsError creates a matcher that checks if an error is non-nil.

func IsFalse#

func IsFalse() Matcher[bool]

IsFalse checks if a boolean is false.

func IsNil#

func IsNil[T any]() Matcher[*T]

IsNil creates a matcher that checks if a pointer is nil.

func IsNotEmpty#

func IsNotEmpty[T any]() Matcher[[]T]

IsNotEmpty creates a matcher that checks if a slice has at least one element.

func IsNotNil#

func IsNotNil[T any]() Matcher[*T]

IsNotNil creates a matcher that checks if a pointer is not nil.

func IsTrue#

func IsTrue() Matcher[bool]

IsTrue checks if a boolean is true.

func IsZero#

func IsZero[T any]() Matcher[T]

IsZero checks if a value is the zero value for its type.

func LessThan#

func LessThan[T interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]

LessThan creates a matcher for numeric types.

func LessThanOrEqual#

func LessThanOrEqual[T interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64
}](threshold T) Matcher[T]

LessThanOrEqual creates a matcher for numeric types.

func MapHasSize#

func MapHasSize[K comparable, V any](expectedSize int) Matcher[map[K]V]

MapHasSize creates a matcher that checks if a map has exactly the expected size.

func MatchesPattern#

func MatchesPattern(regex *regexp.Regexp) Matcher[string]

MatchesPattern creates a matcher that checks if a string matches the given compiled regex.

func MatchesRegex#

func MatchesRegex(pattern string) Matcher[string]

MatchesRegex creates a matcher that checks if a string matches the given regex pattern. The pattern is compiled internally; if compilation fails, the match will fail.

func NoErr#

func NoErr() Matcher[error]

NoErr creates a matcher that checks if an error is nil. This is a convenience matcher for the common case of asserting no error occurred.

func None#

func None[T any](matcher Matcher[T]) Matcher[[]T]

None creates a matcher that checks if no elements in a slice match the given matcher.

func Not#

func Not[T any](matcher Matcher[T]) Matcher[T]

Not negates a matcher.

func PointsTo#

func PointsTo[T any](matcher Matcher[T]) Matcher[*T]

PointsTo creates a matcher that checks if a pointer points to a value matching the given matcher. Returns false if the pointer is nil.

func WithinDuration#

func WithinDuration(expected time.Time, delta time.Duration) Matcher[time.Time]

WithinDuration creates a matcher that checks if a time is within delta duration of the expected time. This is useful for fuzzy time comparisons where exact equality isn’t practical.

type MatcherFunc#

MatcherFunc is a function that implements the Matcher interface.

type MatcherFunc[T any] func(T) MatchResult

func (MatcherFunc[T]) Matches#

func (f MatcherFunc[T]) Matches(actual T) MatchResult

type Maybe#

Maybe holds an optional Gen.

type Maybe[V any] struct {
    // contains filtered or unexported fields
}

func Some#

func Some[V any](gen Gen[V]) Maybe[V]

Some creates a Maybe with a generator.

func (Maybe[V]) GetValue#

func (m Maybe[V]) GetValue(s Source, label string) V

GetValue draws the value from this Maybe’s generator. Panics if the Maybe is not set. Use IsSet() to check first.

func (Maybe[V]) GetWithGenerator#

func (m Maybe[V]) GetWithGenerator(s Source, label string, defGen Gen[V]) V

GetWithGenerator returns the set value if present, otherwise draws from the default generator. This is used by generated factory code to support composable generator defaults. The Source parameter can be either *PrimitivesGen (deterministic) or *conjecture.ConjectureData (property testing).

func (Maybe[V]) IsSet#

func (m Maybe[V]) IsSet() bool

IsSet returns true if this Maybe has a value.

type Opt#

Opt applies to a spec S (not the final instance).

type Opt[S any] func(*S)

func Compose#

func Compose[S any](opts ...Opt[S]) Opt[S]

func SetLit#

func SetLit[S any, V any](assign func(*S, Maybe[V]), v V) Opt[S]

Spec option composition helpers.

func SetWith#

func SetWith[S any, V any](assign func(*S, Maybe[V]), gen Gen[V]) Opt[S]

type Primitives#

type Primitives interface {
    Next() uint64
    Bool() bool
    Int() int
    IntN(max int) int
    Int64() int64
    Uint64() uint64
    Float64() float64
    String() string
    StringWith(prefix string) string
    Bytes() []byte
    BytesN(n int) []byte
    Time() time.Time
    TimeAtOffset(d time.Duration) time.Time
    Duration() time.Duration
    ID() string
    UUID() uuid.UUID
}

type PrimitivesGen#

PrimitivesGen is a deterministic generator for factory test data

type PrimitivesGen struct {
    // contains filtered or unexported fields
}

func New#

func New(opts ...PrimitivesOption) *PrimitivesGen

func (*PrimitivesGen) Bool#

func (g *PrimitivesGen) Bool() bool

Bool always returns false for deterministic, minimal test data generation. This is intentional - Gen is for factories, not property testing. For random booleans, use PropertyPrimitives.

func (*PrimitivesGen) Bytes#

func (g *PrimitivesGen) Bytes() []byte

func (*PrimitivesGen) BytesN#

func (g *PrimitivesGen) BytesN(n int) []byte

func (*PrimitivesGen) DrawBits#

func (g *PrimitivesGen) DrawBits(n int) uint64

DrawBits implements Source interface. Returns bits from the counter for deterministic, predictable generation.

func (*PrimitivesGen) Duration#

func (g *PrimitivesGen) Duration() time.Duration

func (*PrimitivesGen) EndInterval#

func (g *PrimitivesGen) EndInterval()

EndInterval implements Source interface. No-op for Gen since it doesn’t track intervals (only used for property testing).

func (*PrimitivesGen) Float64#

func (g *PrimitivesGen) Float64() float64

func (*PrimitivesGen) ID#

func (g *PrimitivesGen) ID() string

func (*PrimitivesGen) Int#

func (g *PrimitivesGen) Int() int

func (*PrimitivesGen) Int64#

func (g *PrimitivesGen) Int64() int64

func (*PrimitivesGen) IntN#

func (g *PrimitivesGen) IntN(max int) int

func (*PrimitivesGen) IsDeterministic#

func (g *PrimitivesGen) IsDeterministic() bool

IsDeterministic implements Source interface. Returns true because Gen produces predictable, friendly values.

func (*PrimitivesGen) Next#

func (g *PrimitivesGen) Next() uint64

func (*PrimitivesGen) StartInterval#

func (g *PrimitivesGen) StartInterval(label string)

StartInterval implements Source interface. No-op for Gen since it doesn’t track intervals (only used for property testing).

func (*PrimitivesGen) String#

func (g *PrimitivesGen) String() string

func (*PrimitivesGen) StringWith#

func (g *PrimitivesGen) StringWith(prefix string) string

func (*PrimitivesGen) Time#

func (g *PrimitivesGen) Time() time.Time

func (*PrimitivesGen) TimeAtOffset#

func (g *PrimitivesGen) TimeAtOffset(d time.Duration) time.Time

func (*PrimitivesGen) UUID#

func (g *PrimitivesGen) UUID() uuid.UUID

func (*PrimitivesGen) Uint64#

func (g *PrimitivesGen) Uint64() uint64

func (*PrimitivesGen) WriteLog#

func (g *PrimitivesGen) WriteLog(msg string)

WriteLog implements Source interface. Appends to the log if logging is enabled.

type PrimitivesOption#

type PrimitivesOption func(*PrimitivesGen)

func WithBaseTime#

func WithBaseTime(t time.Time) PrimitivesOption

func WithPrefix#

func WithPrefix(p string) PrimitivesOption

func WithStart#

func WithStart(start uint64) PrimitivesOption

func WithTimeStep#

func WithTimeStep(step time.Duration) PrimitivesOption

type PropertyOption#

PropertyOption configures property testing behavior.

type PropertyOption func(*propertyConfig)

func MaxShrinks#

func MaxShrinks(n int) PropertyOption

MaxShrinks sets the maximum number of shrinking attempts. Default is 1000.

func MaxTests#

func MaxTests(n int) PropertyOption

MaxTests sets the maximum number of test iterations to run. Default is 100.

func Seed#

func Seed(seed int64) PropertyOption

Seed sets the random seed for deterministic test generation. This is primarily used to reproduce failures. Default is based on the current time.

type ShrinkBuffer#

ShrinkBuffer is a mutable buffer for trying shrinking modifications. It wraps a byte slice and provides operations for deletion, minimization, and reordering.

type ShrinkBuffer struct {
    // contains filtered or unexported fields
}

func NewShrinkBuffer#

func NewShrinkBuffer(data []byte) *ShrinkBuffer

NewShrinkBuffer creates a new shrink buffer from the given data.

func (*ShrinkBuffer) Data#

func (sb *ShrinkBuffer) Data() []byte

Data returns a copy of the current buffer contents.

func (*ShrinkBuffer) DeleteRange#

func (sb *ShrinkBuffer) DeleteRange(start, end int) bool

DeleteRange deletes bytes from [start, end). Returns true if the deletion was successful, false if indices are invalid.

func (*ShrinkBuffer) Len#

func (sb *ShrinkBuffer) Len() int

Len returns the length of the buffer.

func (*ShrinkBuffer) MinimizeByte#

func (sb *ShrinkBuffer) MinimizeByte(index int, delta byte) bool

MinimizeByte attempts to reduce the value at index by delta. Returns true if successful, false if the result would be negative or index is invalid.

func (*ShrinkBuffer) SetByte#

func (sb *ShrinkBuffer) SetByte(index int, value byte) bool

SetByte sets the byte at index to value. Returns true if successful, false if index is invalid.

func (*ShrinkBuffer) Swap#

func (sb *ShrinkBuffer) Swap(i, j int) bool

Swap swaps the bytes at indices i and j. Returns true if successful, false if indices are invalid.

type Shrinker#

Shrinker orchestrates the shrinking process using multiple passes. It maintains the best (shortest/simplest) failing example found so far.

type Shrinker struct {
    // contains filtered or unexported fields
}

func NewShrinker#

func NewShrinker(data []byte, intervals []Interval, testFunc func([]byte) bool) *Shrinker

NewShrinker creates a new shrinker for the given failing test case. testFunc should return true if the test still fails for the given byte stream.

func (*Shrinker) Calls#

func (s *Shrinker) Calls() int

Calls returns the number of test executions performed during shrinking.

func (*Shrinker) Current#

func (s *Shrinker) Current() []byte

Current returns the best failing example found so far.

func (*Shrinker) Shrink#

func (s *Shrinker) Shrink() []byte

Shrink runs all shrinking passes and returns the minimized failing example. This is the main entry point for shrinking.

It orchestrates multiple passes, running them in rounds until a fixed point is reached (no more shrinking possible) or the call budget is exhausted.

type SliceGenerator#

SliceGenerator provides fluent API for slice generation

type SliceGenerator[T any] struct {
    // contains filtered or unexported fields
}

func Slice#

func Slice[T any](elem Gen[T]) *SliceGenerator[T]

Slice creates a slice generator

func (*SliceGenerator[T]) Draw#

func (g *SliceGenerator[T]) Draw(d conjecture.DataSource) ([]T, error)

Draw implements Gen[[]T]

func (*SliceGenerator[T]) Filter#

func (g *SliceGenerator[T]) Filter(pred func([]T) bool) Gen[[]T]

Filter returns a generator that only produces slices satisfying the predicate

func (*SliceGenerator[T]) Len#

func (g *SliceGenerator[T]) Len(n int) *SliceGenerator[T]

Len sets exact slice length

func (*SliceGenerator[T]) MaxLen#

func (g *SliceGenerator[T]) MaxLen(n int) *SliceGenerator[T]

MaxLen sets maximum slice length

func (*SliceGenerator[T]) MinLen#

func (g *SliceGenerator[T]) MinLen(n int) *SliceGenerator[T]

MinLen sets minimum slice length

func (*SliceGenerator[T]) NonEmpty#

func (g *SliceGenerator[T]) NonEmpty() *SliceGenerator[T]

NonEmpty ensures slice has at least one element

func (*SliceGenerator[T]) String#

func (g *SliceGenerator[T]) String() string

String implements Gen[[]T]

type Source#

Source provides data for generators. It has two modes:

  • Deterministic (Gen): counter-based, produces friendly values like “user_1”
  • Random (randomSource): PRNG-based, explores full type space for property testing
type Source interface {
    // DrawBits generates n random bits as a uint64.
    DrawBits(n int) uint64

    // WriteLog appends a message to the log if logging is enabled.
    WriteLog(msg string)

    // IsDeterministic returns true if this source generates predictable,
    // friendly values (like Gen). Returns false for random property testing.
    IsDeterministic() bool

    // StartInterval marks the beginning of a labeled interval in the byte stream.
    // Generators should call this at the start of Draw() to enable structure-aware shrinking.
    StartInterval(label string)

    // EndInterval marks the end of the current interval.
    // Generators should call this at the end of Draw().
    EndInterval()
}

func AsSource#

func AsSource(d conjecture.DataSource) Source

AsSource converts a DataSource to a Source (exported version for generated code).

type SpecFactory#

SpecFactory builds values from specs.

type SpecFactory[T any, S any] struct {
    S       Source
    NewSpec func() S
    Build   BuildWithSpec[T, S]
}

func NewSpecFactory#

func NewSpecFactory[T any, S any](s Source, newSpec func() S, build BuildWithSpec[T, S]) *SpecFactory[T, S]

func (*SpecFactory[T, S]) Make#

func (f *SpecFactory[T, S]) Make(opts ...Opt[S]) T

func (*SpecFactory[T, S]) Many#

func (f *SpecFactory[T, S]) Many(n int, opts ...Opt[S]) []T

type StringGenerator#

StringGenerator provides a fluent API for building string generators

type StringGenerator struct {
    // contains filtered or unexported fields
}

func String#

func String() *StringGenerator

String creates a string generator

func (*StringGenerator) ASCII#

func (g *StringGenerator) ASCII() *StringGenerator

ASCII generates only ASCII characters

func (*StringGenerator) Alpha#

func (g *StringGenerator) Alpha() *StringGenerator

Alpha generates only alphabetic characters

func (*StringGenerator) AlphaNum#

func (g *StringGenerator) AlphaNum() *StringGenerator

AlphaNum generates only alphanumeric characters

func (*StringGenerator) Draw#

func (g *StringGenerator) Draw(d conjecture.DataSource) (string, error)

Draw implements Gen[string]

func (*StringGenerator) ExampleHint#

func (g *StringGenerator) ExampleHint(hint string) *StringGenerator

ExampleHint sets a hint for deterministic generation. When using PrimitivesGen (factory mode), generates strings like “id_1”, “id_2” instead of “str_1”, “str_2”. Has no effect in property testing mode (ConjectureData).

func (*StringGenerator) Filter#

func (g *StringGenerator) Filter(pred func(string) bool) Gen[string]

Filter returns a generator that only produces strings satisfying the predicate

func (*StringGenerator) Len#

func (g *StringGenerator) Len(n int) *StringGenerator

Len sets exact length

func (*StringGenerator) MaxLen#

func (g *StringGenerator) MaxLen(n int) *StringGenerator

MaxLen sets the maximum length

func (*StringGenerator) MinLen#

func (g *StringGenerator) MinLen(n int) *StringGenerator

MinLen sets the minimum length

func (*StringGenerator) NonEmpty#

func (g *StringGenerator) NonEmpty() *StringGenerator

NonEmpty ensures string is not empty

func (*StringGenerator) Prefix#

func (g *StringGenerator) Prefix(p string) *StringGenerator

Prefix adds a prefix to generated strings

func (*StringGenerator) Printable#

func (g *StringGenerator) Printable() *StringGenerator

Printable generates only printable ASCII

func (*StringGenerator) String#

func (g *StringGenerator) String() string

String implements Gen[string]

func (*StringGenerator) Suffix#

func (g *StringGenerator) Suffix(s string) *StringGenerator

Suffix adds a suffix to generated strings

type T#

T is a testing helper for property-based tests. It implements the TestingT interface and can be used with AssertThat and other matchers. Unlike testing.T, calling Fatalf does not immediately terminate the test process, but instead panics with a sentinel value to stop the current property iteration.

type T struct {
    Data   *conjecture.ConjectureData // ConjectureData for drawing values
    Source Source                     // Deprecated: kept for backward compatibility, will panic if used
    // contains filtered or unexported fields
}

func (*T) Assume#

func (t *T) Assume(condition bool)

Assume skips the current property test iteration if the condition is false. This is useful for filtering generated values that don’t meet preconditions. Property will track how many tests were skipped and warn if the skip rate is high.

Example:

Property(t, func(t *T) {
    n := Int().Range(1, 100).Draw(t, "n")
    t.Assume(isPrime(n))  // Skip if not prime
    // Test with prime numbers only
})

func (*T) Errorf#

func (t *T) Errorf(format string, args ...any)

Errorf records an error but allows the property test to continue. Multiple assertions can be checked before the property fails.

func (*T) Fatalf#

func (t *T) Fatalf(format string, args ...any)

Fatalf records an error and immediately stops this property test iteration.

func (*T) Helper#

func (t *T) Helper()

Helper marks the calling function as a test helper. This is a no-op for property testing but satisfies the TestingT interface.

func (*T) Logf#

func (t *T) Logf(format string, args ...any)

Logf logs a message. During normal test execution, logs are discarded to avoid spam from multiple iterations. During the final replay of a failing test, logs are forwarded directly to testing.T.Logf with correct line attribution using the Helper() mechanism.

type TestingT#

TestingT is the minimal interface required by AssertThat and RequireThat. Both *testing.T and *testing.B satisfy this interface.

type TestingT interface {
    Helper()
    Errorf(format string, args ...interface{})
    Fatalf(format string, args ...interface{})
    Logf(format string, args ...interface{})
}

Generated by gomarkdoc