Skip to content

Latest commit

 

History

537 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Core helpers for darvaza.org projects

Go Reference Go Report Card codecov

This package contains simple mechanisms used by other darvaza.org projects. It's not allowed to have dependencies outside of Go's Standard Library, and if something should be on a subdirectory, it shouldn't be here.

Type Constraints

Generic type constraints for use with Go generics:

  • Signed - signed integer types.
  • Unsigned - unsigned integer types.
  • Integer - all integer types (signed and unsigned).
  • Float - floating-point types.
  • Complex - complex number types.
  • Bool - boolean type.
  • String - string type.
  • Ordered - types that support ordering operations.

Context

Context Keys

  • NewContextKey[T](name) - creates a new type-safe key bound to specified type and friendly name.
  • ContextKey[T].WithValue(ctx, value) - safely attach value to context, comparable to standard context.WithValue().
  • ContextKey[T].Get(ctx) - extracts value bound to this key in context, returns (value, found) with nil receiver safety.

Timeout Utilities

  • WithTimeout(parent, duration) - equivalent to context.WithDeadline() but takes duration instead of absolute time. Returns parent context and no-op cancel for zero/negative durations.
  • WithTimeoutCause(parent, duration, cause) - equivalent to context.WithDeadlineCause() but takes duration instead of absolute time. Attaches custom cause error to timeout context.

Network Utilities

IP Address Functions

  • GetIPAddresses() - get IP addresses as netip.Addr.
  • GetNetIPAddresses() - get IP addresses as net.IP.
  • GetStringIPAddresses() - get IP addresses as strings.
  • AddrFromNetIP(ip) - convert net.IP to netip.Addr.
  • ParseAddr(s) - parse string to netip.Addr.
  • ParseNetIP(s) - parse string to net.IP.

Host/Port Functions

Parsing and Splitting

  • SplitHostPort(hostport) - enhanced version of net.SplitHostPort that accepts portless strings and validates both host and port. Supports IPv6 addresses, international domain names, and descriptive error messages.
  • SplitAddrPort(addrport) - splits IP address and optional port into netip.Addr and uint16. Validates address format and port range (1-65535), returns zero values for portless addresses.

Joining and Construction

  • JoinHostPort(host, port) - enhanced version of net.JoinHostPort that validates inputs and returns portless host when port is empty. Properly handles IPv6 bracketing and international domain names.
  • MakeHostPort(hostport, defaultPort) - constructs validated host:port string from input with optional default port. Rejects port 0 in input, supports portless output when default is 0.
  • AddrPort(v) - extracts netip.AddrPort from various network types (*net.TCPAddr, *net.UDPAddr, etc.), returns (AddrPort, bool).

Interface Functions

  • GetInterfacesNames() - get network interface names.

Generic Utilities

Zero Value Utilities

Zero Value Creation

  • Zero[T](_ *T) - returns the zero value for type T using a typed nil pointer for type inference. Supports all Go types including complex generics, interfaces, and custom types.

Zero Value Detection

  • IsZero(v) - reports whether a value is in an uninitialized state and ready to be set. Answers the question: "Is this value uninitialized and ready to be set?"

Key semantic distinctions:

  • Nil vs Empty: []int(nil) returns true (needs initialization), []int{} returns false (already initialized).
  • Pointer States: (*int)(nil) returns true (can be assigned), new(int) returns false (already points to memory).
  • Interface Support: Types implementing IsZero() bool are handled via their method, enabling custom zero semantics.

Nil Value Detection

  • IsNil(v) - reports whether a value is nil (typed or untyped). Answers the question: "Is this value nil?"

Key distinctions from IsZero:

  • Scope: Only checks for nil state, not zero state.
  • Basic Types: IsNil(0) returns false (integers cannot be nil), IsZero(0) returns true (zero integer is uninitialized).
  • Collections: IsNil([]int{}) returns false (empty slice is not nil), IsZero([]int{}) returns false (empty slice is initialized).
  • Structs: IsNil(struct{}{}) returns false (structs cannot be nil), IsZero(struct{}{}) returns true (zero struct is uninitialized).

Same Value Detection

  • IsSame(a, b) - reports whether two values are the same. For reference types (slices, maps, pointers), compares by pointer equality. For value types (numbers, strings, booleans), compares by equal values. Two nils of the same type are considered the same.

Safe Comparison

  • AreComparable(values...) - reports whether the values are safe operands of ==: a true result guarantees no comparison between them can panic. Untyped nils are safe.
  • AreEqual(values...) - reports whether each value equals the next, as == would decide, without ever panicking, returning (is, known bool). Values of the same comparable type are tested with ==; otherwise typed nils, identity, or the value's own Equal(T) bool method settle the answer, and slices are compared element by element, one level deep. Anything else is reported as unknown rather than resolved by deep comparison; callers that need a decision anyway can fall back to reflect.DeepEqual when it is not known.

Other Utilities

  • Coalesce[T](values...) returns the first non-zero value.
  • IIf[T](condition, ifTrue, ifFalse) conditional expression.

Type Conversion

  • As[T,V](v) attempts to convert value to target type
  • AsFn[T,V](v, fn) converts value using a provided function
  • AsError[T](v) attempts to convert value to error
  • AsErrors[T](v) attempts to convert value to error slice

Slice Operations

Search and Comparison

  • SliceContains[T](slice, value) - deprecated, use slices.Contains.
  • SliceContainsFn[T](slice, value, eq) - check containment with custom equality.
  • SliceEqual[T](a, b) - deprecated, use slices.Equal.
  • SliceEqualFn[T](a, b, eq) - deprecated, use slices.EqualFunc.

Transformation

  • SliceAs[T,V] / SliceAsFn[T,V] - convert slice elements to different type.
  • SliceMap[T1,T2](slice, fn) - transform each element with cumulative function.
  • SliceReplaceFn[T](slice, fn) - replace/filter elements in-place.
  • SliceCopy[T](slice) - deprecated, use slices.Clone.
  • SliceCopyFn[T](slice, fn) - create filtered/transformed copy.

Set Operations

  • SliceMinus[T](a, b) - elements in a but not in b.
  • SliceMinusFn[T](a, b, eq) - set difference with custom equality.
  • SliceUnique[T](slice) - return slice with unique elements only.
  • SliceUniqueFn[T](slice, eq) - unique elements with custom equality.
  • SliceUniquify[T](ptr) - remove duplicates in-place, modify original.
  • SliceUniquifyFn[T](ptr, eq) - remove duplicates with custom equality.

Sorting and Ordering

  • SliceSort[T](slice, cmp) - deprecated, use slices.SortFunc.
  • SliceSortFn[T](slice, less) - sort using less function (returns bool).
  • SliceSortOrdered[T](slice) - deprecated, use slices.Sort.
  • SliceReverse[T](slice) - deprecated, use slices.Reverse.
  • SliceReversed[T](slice) - return reversed copy.
  • SliceReversedFn[T](slice, fn) - return transformed and reversed copy.

Utilities

  • SliceRandom[T](slice) - select random element, returns (value, found).
  • SliceP[T](slice,p) - return the p-th percentile of the slice (p must be 0.0-1.0). Sorts the slice in-place. Returns the zero value for empty slices or invalid p.

List Operations (container/list)

Search and Membership

  • ListContains[T](list, value) - check if list contains element with default equality.
  • ListContainsFn[T](list, value, eq) - check if list contains element with custom equality function.

Iteration

  • ListForEach[T](list, fn) - iterate forward over list values until fn returns true.
  • ListForEachElement(list, fn) - iterate forward over list elements until fn returns true.
  • ListForEachBackward[T](list, fn) - iterate backward over list values until fn returns true.
  • ListForEachBackwardElement(list, fn) - iterate backward over list elements until fn returns true.

Copying and Transformation

  • ListCopy[T](list) - create shallow copy of list.
  • ListCopyFn[T](list, fn) - create filtered/transformed copy with helper function.

Map Operations

Basic Map Functions

  • MapContains[K]() checks if a map contains a key.
  • MapValue[K,V]() returns the value for a key, or a fallback value.
  • Keys[K,T]() returns a slice of the keys in the map.
  • SortedKeys[K,T]() returns a sorted slice of the keys.
  • SortedValues[K,T]() returns values sorted by key.
  • SortedValuesCond[K,T]() returns filtered values sorted by key.
  • SortedValuesUnlikelyCond[K,T]() like SortedValuesCond but more efficient.

Map List Operations

  • MapListContains[K,T] / MapListContainsFn[K,T]
  • MapListForEach[K,T] / MapListForEachElement[K]
  • MapListInsert[K,T] / MapListAppend[K,T]
  • MapListInsertUnique[K,T] / MapListInsertUniqueFn[K,T]
  • MapListAppendUnique[K,T] / MapListAppendUniqueFn[K,T]
  • MapListCopy[T] / MapListCopyFn[K,V]

Map All List Operations

  • MapAllListContains[K,T] / MapAllListContainsFn[K,T]
  • MapAllListForEach[K,T] / MapAllListForEachElement[K]

Error Handling

Standard Error Variables

Predefined error values for common conditions:

  • ErrNotImplemented - functionality not yet implemented.
  • ErrTODO - placeholder for future implementation.
  • ErrExists - resource already exists.
  • ErrNotExists - resource does not exist.
  • ErrInvalid - invalid input or state.
  • ErrUnknown - unknown or unspecified error.
  • ErrNilReceiver - method called on nil receiver.
  • ErrUnreachable - indicates impossible condition.

String Errors

The StringError type is an error whose message is the string itself. Because its underlying type is string, sentinels can be declared as constants rather than variables:

const ErrClosed core.StringError = "already closed"
  • Values with equal text compare equal, so errors.Is matches by value.
  • .AsError() returns nil for the empty string, following the AsError() convention used across the package.
  • .OK() reports whether the string is empty (no error), the inverse of a non-nil .AsError().
  • .IsZero() reports whether the string is empty, so IsZero recognises a zero StringError through its own method.
  • NewStringError(format, args...) - build one from a formatted message, returning nil when the result is empty. Without arguments the format is used verbatim, leaving a literal % untouched.

Error Wrapping

The Unwrappable interface represents the classic Unwrap() error pattern, implemented by WrappedError. The Errors interface represents multi-error containers with Errors() []error.

Error wrapping functions:

  • Wrap(err, note) - wrap with simple string note.
  • Wrapf(err, format, args...) - wrap with formatted note.
  • QuietWrap(err, note) - wrap without including original error text.
  • Unwrap(err) []error - extract all sub-errors from wrapped errors.

Compound Errors

The CompoundError type aggregates multiple errors:

  • Implements both Unwrap() []error and Errors() []error interfaces.
  • .AppendError(err) / .Append(errs...) - add errors.
  • .AsError() - convert to single error or nil.
  • .OK() - check if no errors.

Panic Handling

The PanicError type wraps panic values with stack traces:

  • NewPanicError() / NewPanicErrorf() - create panic errors.
  • NewPanicWrap() / NewPanicWrapf() - wrap existing errors as panics.
  • Panic() / Panicf() / PanicWrap() / PanicWrapf() - panic with PanicError.

Panic recovery utilities:

  • Recovered interface - marks errors from recovered panics.
  • AsRecovered(v) - convert recover() result to error.
  • Catcher type - safely call functions that might panic.
  • Catch(fn) - execute function, returning error if panic occurs.
defer func() {
  if err := core.AsRecovered(recover()); err != nil {
    // handle panic as error
  }
}()

Must/Maybe Utilities

Convenience functions for common error-handling patterns:

  • Must[T](value T, err error) T - returns value or panics with PanicError if err is not nil. Follows the common Go pattern of Must* functions for cases where errors should never occur.
  • Maybe[T](value T, err error) T - always returns the value, ignoring any error. When an error occurs, the returned value may be the zero value of type T depending on the function that produced it.
  • MustOK[T](value T, ok bool) T - returns value or panics with PanicError if ok is false. Useful for operations that should always succeed, such as map access or type assertions that are guaranteed to be valid.
  • MaybeOK[T](value T, ok bool) T - always returns the value, ignoring the ok flag. When ok is false, the returned value is typically the zero value of type T from the failed operation.
  • MustT[T](value any) T - equivalent to MustOK(As[any, T](value)). Returns converted value or panics with PanicError if type conversion fails.
  • MaybeT[T](value any) T - equivalent to MaybeOK(As[any, T](value)). Returns converted value on success, or the zero value of type T if conversion fails.

All these utilities work together with the As[any, T] function, which returns (value, ok) for type conversion, allowing custom handling of conversion failures.

// Must - panic on error (use in tests, config loading, etc.)
config := Must(loadConfig("config.json"))  // panics if loadConfig fails
conn := Must(net.Dial("tcp", "localhost:8080"))  // panics if dial fails

// Maybe - ignore errors, proceed with values (may be zero values)
content := Maybe(os.ReadFile("optional.txt"))  // []byte{} if file missing
count := Maybe(strconv.Atoi(userInput))       // 0 if parsing fails

// MustOK - panic on failure (use when operation should always succeed)
value := MustOK(MapValue(m, "key", 0))  // panics if key doesn't exist
str := MustOK(As[any, string](v))       // panics if v is not a string

// MaybeOK - ignore ok flag, proceed with values (zero values on failure)
value := MaybeOK(MapValue(m, "key", 0))  // 0 if key doesn't exist
str := MaybeOK(As[any, string](v))       // "" if type assertion fails

// MustT - equivalent to MustOK(As[any, T](value))
str := MustT[string](value)  // panics if value is not a string
num := MustT[int](value)     // panics if value is not an int

// MaybeT - equivalent to MaybeOK(As[any, T](value))
str := MaybeT[string](value)  // "" (zero value) if value is not a string
num := MaybeT[int](value)     // 0 (zero value) if value is not an int

// As - the building block for type conversion with custom handling
if str, ok := As[any, string](value); ok {
    // use converted string
} else {
    str = "custom default"  // your own fallback logic
}

For error-only preconditions (no value to return), the MustNoError family panics through ErrUnreachable rather than returning a value:

  • MustNoError(err error) - panics with PanicError wrapping ErrUnreachable if err is not nil. The no-value sibling of Must, for guarding a bare error whose non-nil return signals an impossible path.
  • MustNoErrorExcept(err error, allowed ...error) - like MustNoError, but does not panic when err matches one of the allowed errors (recursive match via IsError).
  • MustNoErrorExceptFn(err error, check func(error) bool) - like MustNoErrorExcept, but matches via a predicate (recursive match via IsErrorFn), for allow-lists that aren't a fixed set of sentinels.

Unreachable Conditions

For indicating impossible code paths:

  • NewUnreachableError() - create unreachable error.
  • NewUnreachableErrorf(format, args...) - create formatted unreachable error.

These create PanicError instances with stack traces.

Temporary and Timeout Errors

Special error types for network-style temporary and timeout conditions:

  • TemporaryError type - implements Temporary() bool and IsTemporary() bool interfaces for marking recoverable errors.
  • NewTemporaryError(err) - wrap error as temporary condition.
  • NewTimeoutError(err) - wrap error as timeout condition with both temporary and timeout properties.
  • IsTemporary(err) - recursively test if error chain contains temporary condition via Temporary() or IsTemporary() methods.
  • CheckIsTemporary(err) - test single error for temporary condition without unwrapping chain, returns (is, known) tuple.
  • IsTimeout(err) - recursively test if error chain contains timeout condition via Timeout() or IsTimeout() methods.
  • CheckIsTimeout(err) - test single error for timeout condition without unwrapping chain, returns (is, known) tuple.

Error Testing and Utilities

  • IsError(err, errs...) - recursively test whether an error chain matches any of the targets, by identity or the error's own Is(error) bool method.
  • IsErrorFn(check, errs...) / IsErrorFn2(check, errs...) - recursive error testing with custom checker functions.
  • NewCheckErrorIsIn(targets) / NewCheckErrorIsIn2(targets) - build the per-node check functions behind IsError, for composing the same identity-or-Is matching with IsErrorFn / IsErrorFn2.
  • CoalesceError(errs...) - return first non-nil error from argument list.

Stack Tracing

Stack tracing utilities for debugging, error reporting, and call context:

Core Types

  • Frame - represents a single function call frame with source location.
  • Stack - slice of frames representing a complete call stack.
  • MaxDepth - maximum stack capture depth (32 frames).
  • CallStacker interface - types that can provide their call stack.

Stack Capture Functions

Frame Capture

  • Here() - capture the current stack frame where called. Returns nil if capture fails. Useful for immediate calling context.
  • StackFrame(skip) - capture a specific frame in the call stack, skipping the specified number of levels. Returns nil if insufficient frames.

Complete Stack Capture

  • StackTrace(skip) - capture complete call stack starting from skip level. Returns empty Stack on failure. Maximum depth limited by MaxDepth.

Frame Information Methods

Function Names

  • Frame.Name() - full qualified function name including package path (e.g., "darvaza.org/core.TestFunction").
  • Frame.FuncName() - function name only without package qualification (e.g., "TestFunction").
  • Frame.PkgName() - package path portion only (e.g., "darvaza.org/core").
  • Frame.SplitName() - split full name into (package, function) components. Handles generic functions by ignoring "[...]" suffixes.

Source Location

  • Frame.File() - full path to source file containing the function.
  • Frame.Line() - line number within source file (0 if unavailable).
  • Frame.FileLine() - formatted "file:line" string for display.

Formatting

  • Frame.Format(fmt.State, rune) - implements fmt.Formatter interface with support for multiple format verbs:

    • %s - source file basename.
    • %d - line number.
    • %n - function name (short form).
    • %v - equivalent to %s:%d.
    • %+s - function name + full file path (newline separated).
    • %+n - full qualified function name.
    • %+v - equivalent to %+s:%d.
  • Stack.Format(fmt.State, rune) - formats entire stack with same verbs as Frame plus '#' flag support:

    • %#s, %#n, %#v - each frame on new line.
    • %#+s, %#+n, %#+v - numbered frames with [index/total] prefix.

Usage Examples

// Capture current location
frame := Here()
if frame != nil {
    fmt.Printf("Called from %s at %s", frame.FuncName(), frame.FileLine())
}

// Capture complete stack for error reporting
stack := StackTrace(1) // skip current function
fmt.Printf("Stack trace:%+v", stack)

// Numbered stack output
fmt.Printf("Debug stack:%#+v", stack)

Testing Utilities

This package provides comprehensive public testing utilities for both internal library tests and external library users.

T Interface and MockT

  • T interface - abstracts testing functionality for both *testing.T and mock implementations.
  • MockT - thread-safe mock testing.T implementation with error/log collection, helper tracking, state inspection (HasErrors(), HasLogs(), LastError(), LastLog()), reset capabilities, and full Fatal/FailNow support with panic recovery via the Run() method.

Cross-Compatible Test Functions

For test utilities that need to work with both *testing.T and MockT, use interface type assertions to detect Run() method support. This enables nested subtests that gracefully degrade to direct function calls:

func doRun(t T, name string, fn func(T)) {
    switch tt := t.(type) {
    case interface { Run(string, func(*testing.T)) bool }:
        tt.Run(name, func(subT *testing.T) { fn(subT) })
    case interface { Run(string, func(T)) bool }:
        tt.Run(name, fn)
    default:
        fn(t) // Fallback for simple T implementations
    }
}

Test Helpers

  • S[T](values...) - concise slice creation: S(1, 2, 3) instead of []int{1, 2, 3}.
  • S[T]() - empty slice creation: S[string]() instead of []string{}.

Assertion Functions

All assertions return boolean results, log successful cases, and work with both *testing.T and MockT:

Basic Assertions

  • AssertEqual[T](t, expected, actual, name...) - generic value comparison, decided by AreEqual.
  • AssertNotEqual[T](t, expected, actual, name...) - generic inequality comparison, decided by AreEqual.
  • AssertSliceEqual[T](t, expected, actual, name...) - slice comparison, settling length and nil-ness first, then the elements via AreEqual.
  • AssertDeepEqual[T](t, expected, actual, name...) - value comparison using reflect.DeepEqual.
  • AssertNotDeepEqual[T](t, expected, actual, name...) - inequality using reflect.DeepEqual.
  • AssertSame(t, expected, actual, name...) - same value/reference comparison using pointer equality for reference types, value equality for basic types.
  • AssertNotSame(t, expected, actual, name...) - different value/reference comparison.
  • AssertTrue(t, condition, name...) / AssertFalse(t, condition, name...) - boolean assertions.
  • AssertNil(t, value, name...) / AssertNotNil(t, value, name...) - nil checking.
  • AssertContains(t, text, substring, name...) - string containment.
  • AssertNotContain(t, text, substring, name...) - string exclusion.

The Equal family delegates to AreEqual, so it accepts values that aren't comparable and honours an Equal(T) bool method. AssertDeepEqual and its Must form settle what it cannot decide — nested slices, and anything else needing a deep traversal — which the failure names as such.

AssertSliceEqual settles shape before contents: a length difference is reported as a count, and nil-versus-empty by name, since only nil equals nil and both otherwise print as an indistinguishable []. Once the shape matches, the first element known to differ is reported by index, so a long slice needn't be diffed by eye.

Error and Type Assertions

  • AssertError(t, err, name...) / AssertNoError(t, err, name...) - error presence/absence.
  • AssertErrorIs(t, err, target, name...) / AssertNotErrorIs(t, err, target, name...) - error chain presence/absence via errors.Is.
  • AssertErrorIsFn(t, err, targetFn, name...) - error chain checking against a check function via IsErrorFn.
  • AssertErrorAs[E](t, err, name...) - error chain extraction with errors.As, returns (*match, ok).
  • AssertTypeIs[T](t, value, name...) - type assertion with casting, returns (value, ok).
  • AssertPanic(t, fn, expectedPanic, name...) / AssertNoPanic(t, fn, name...) - panic testing with type-aware matching.

Fatal Assertions

All AssertMustFoo() functions call the corresponding AssertFoo() function and automatically call t.FailNow() if the assertion fails, terminating test execution immediately. These follow Go testing conventions where "Fatal" methods terminate execution, similar to t.Error() vs t.Fatal().

Key Differences:

  • AssertFoo() - like t.Error(), logs failure and allows test to continue.
  • AssertMustFoo() - like t.Fatal(), logs failure and terminates test execution.

Fatal Assertion Functions:

  • AssertMustEqual[T](t, expected, actual, name...) - terminate on inequality.
  • AssertMustNotEqual[T](t, expected, actual, name...) - terminate on equality.
  • AssertMustSliceEqual[T](t, expected, actual, name...) - terminate on slice inequality.
  • AssertMustDeepEqual[T](t, expected, actual, name...) - terminate on deep inequality.
  • AssertMustNotDeepEqual[T](t, expected, actual, name...) - terminate on deep equality.
  • AssertMustTrue(t, condition, name...) / AssertMustFalse(t, condition, name...) - terminate on boolean mismatch.
  • AssertMustNil(t, value, name...) / AssertMustNotNil(t, value, name...) - terminate on nil check failure.
  • AssertMustContains(t, text, substring, name...) - terminate if substring not found.
  • AssertMustNotContain(t, text, substring, name...) - terminate if substring found.
  • AssertMustError(t, err, name...) / AssertMustNoError(t, err, name...) - terminate on error expectation mismatch.
  • AssertMustErrorIs(t, err, target, name...) - terminate on error chain mismatch.
  • AssertMustErrorIsFn(t, err, targetFn, name...) - terminate on check function mismatch.
  • AssertMustErrorAs[E](t, err, name...) *E - terminate when no match in the error chain, returns matched value.
  • AssertMustTypeIs[T](t, value, name...) T - terminate on type assertion failure, returns cast value.
  • AssertMustPanic(t, fn, expectedPanic, name...) / AssertMustNoPanic(t, fn, name...) - terminate on panic expectation mismatch.
  • AssertMustSame(t, expected, actual, name...) / AssertMustNotSame(t, expected, actual, name...) - terminate on same-ness mismatch.

Usage Examples:

// Error pattern - logs failure, test continues
AssertEqual(t, expected, actual, "value check")
// execution continues even if assertion fails

// Fatal pattern - logs failure, test terminates
AssertMustEqual(t, expected, actual, "critical value check")
// execution stops here if assertion fails

// Traditional early abort pattern (equivalent to AssertMust*)
if !AssertEqual(t, expected, actual, "critical value") {
    t.FailNow()
}

Advanced Testing Utilities

  • TestCase interface - standardised interface for table-driven tests with Name() and Test(t) methods.
  • RunTestCases[T TestCase](t, cases) - table-driven test runner for TestCase implementations.
  • RunConcurrentTest(t, numWorkers, workerFn) - concurrent testing with goroutines.
  • RunBenchmark(b, setupFn, execFn) - benchmark testing with setup/execution phases.

Documentation

For detailed testing patterns and guidelines:

  • TESTING.md - General testing patterns for all darvaza.org projects
  • TESTING_core.md - Core-specific testing patterns and self-testing approaches

Synchronization

WaitGroup

Enhanced wait group with error handling:

  • WaitGroup - wait group that collects errors.
  • .OnError(fn) - set error handler.
  • .Go(fn) / .GoCatch(fn) - run functions in goroutines.
  • .Wait() - wait for completion.
  • .Err() - get first error.

ErrGroup

Context-aware error group with cancellation:

  • ErrGroup - context-based error group.
  • .SetDefaults() - configure with defaults.
  • .OnError(fn) - set error handler.
  • .Cancel() / .Context() - cancellation control.
  • .Go(fn) / .GoCatch(fn) - run functions with context.
  • .Wait() - wait and return first error.
  • .IsCancelled() / .Cancelled() - check cancellation state.

Deprecated

Development

Requirements: Go 1.25 or later

For detailed development setup, build commands, and AI agent guidance:

  • AGENTS.md - Development guidelines, build system, and testing patterns.

Quick Start

make all    # Full build cycle (get deps, generate, tidy, build)
make test   # Run tests
make tidy   # Format and tidy (run before committing)

See also

About

fundamental set of helpers for darvaza projects

Topics

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Used by

Contributors

Languages