Documentation
¶
Overview ¶
Package replay captures and replays HTTP request snapshots for regression tests.
Index ¶
- Variables
- func Command(handler http.Handler) cli.Command
- func NewRequest(snapshot Snapshot) (*http.Request, error)
- func RequireDeterministic(snapshot Snapshot) error
- func Run(handler http.Handler, snapshot Snapshot) (*httptest.ResponseRecorder, error)
- func ValidateBoundaries(snapshot Snapshot) error
- type Boundary
- type BoundaryError
- type ExpectedResponse
- type Option
- func WithApplicationVersion(version string) Option
- func WithBodyLimit(limit int64) Option
- func WithClock(now func() time.Time) Option
- func WithControlledBoundaries(boundaries ...Boundary) Option
- func WithEnvironment(environment string) Option
- func WithFeatureFlags(flags map[string]string) Option
- func WithHeaders(headers ...string) Option
- func WithPrincipal(ref PrincipalRef) Option
- func WithRedactor(redactor *scrub.Redactor) Option
- func WithUncontrolledBoundaries(boundaries ...Boundary) Option
- type PrincipalRef
- type Snapshot
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnknownBoundary reports a replay boundary name outside the supported set. ErrUnknownBoundary = errors.New("unknown replay boundary") // ErrBoundaryConflict reports a boundary marked as both controlled and uncontrolled. ErrBoundaryConflict = errors.New("conflicting replay boundary") // ErrUncontrolledBoundaries reports a snapshot that still has nondeterministic boundaries. ErrUncontrolledBoundaries = errors.New("uncontrolled replay boundaries") )
Functions ¶
func NewRequest ¶
NewRequest builds a test request from snapshot.
func RequireDeterministic ¶
RequireDeterministic verifies that a snapshot can be used as a stable regression test.
func ValidateBoundaries ¶
ValidateBoundaries verifies that replay boundary metadata uses known names and does not mark a boundary as both controlled and uncontrolled.
Types ¶
type Boundary ¶
type Boundary string
Boundary identifies an application dependency that can make replay nondeterministic.
const ( // BoundaryClock identifies wall-clock time dependencies. BoundaryClock Boundary = "clock" // BoundaryRandomID identifies random identifier dependencies. BoundaryRandomID Boundary = "random_id" // BoundaryExternalHTTP identifies external HTTP dependencies. BoundaryExternalHTTP Boundary = "external_http" // BoundaryEmailDelivery identifies email delivery dependencies. BoundaryEmailDelivery Boundary = "email_delivery" // BoundaryFileWrites identifies file write dependencies. BoundaryFileWrites Boundary = "file_writes" // BoundaryDatabaseState identifies database state dependencies. BoundaryDatabaseState Boundary = "database_state" // BoundaryFeatureFlags identifies feature flag dependencies. BoundaryFeatureFlags Boundary = "feature_flags" )
func NormalizeBoundaries ¶
NormalizeBoundaries trims empty boundary names and preserves first-seen order.
type BoundaryError ¶
type BoundaryError struct {
// Reason is one of ErrUnknownBoundary, ErrBoundaryConflict, or
// ErrUncontrolledBoundaries.
Reason error
// Kind is "controlled" or "uncontrolled" for unknown-boundary errors.
Kind string
// Boundary is the boundary that failed validation.
Boundary Boundary
// Boundaries is the normalized boundary set for nondeterminism errors.
Boundaries []Boundary
// Expected is the supported boundary set for unknown-boundary errors.
Expected []Boundary
}
BoundaryError describes invalid or nondeterministic replay boundary metadata.
func (*BoundaryError) Error ¶
func (e *BoundaryError) Error() string
Error returns a human-readable boundary validation message.
func (*BoundaryError) Unwrap ¶
func (e *BoundaryError) Unwrap() error
Unwrap returns the semantic boundary validation reason.
type ExpectedResponse ¶
type ExpectedResponse struct {
Status int `json:"status"`
Headers map[string][]string `json:"headers,omitempty"`
Body []byte `json:"body,omitempty"`
BodyOmitted bool `json:"body_omitted,omitempty"`
}
ExpectedResponse captures the response assertions used by generated replay tests.
func ExpectedResponseFrom ¶
func ExpectedResponseFrom(response *httptest.ResponseRecorder) (ExpectedResponse, error)
ExpectedResponseFrom captures stable response fields from a replay result.
type Option ¶
type Option func(*captureOptions)
Option configures request snapshot capture.
func WithApplicationVersion ¶
WithApplicationVersion includes the application version in captured snapshots.
func WithBodyLimit ¶
WithBodyLimit captures the request body when it is no larger than limit bytes.
func WithControlledBoundaries ¶
WithControlledBoundaries marks dependencies made deterministic for replay.
func WithEnvironment ¶
WithEnvironment includes the application environment in captured snapshots.
func WithFeatureFlags ¶
WithFeatureFlags includes scrubbed feature flag values in captured snapshots.
func WithHeaders ¶
WithHeaders configures the request headers captured into a snapshot.
func WithPrincipal ¶
func WithPrincipal(ref PrincipalRef) Option
WithPrincipal includes an authenticated principal reference in captured snapshots.
func WithRedactor ¶
WithRedactor configures the snapshot redactor.
func WithUncontrolledBoundaries ¶
WithUncontrolledBoundaries marks dependencies that may make replay nondeterministic.
type PrincipalRef ¶
PrincipalRef identifies an authenticated principal without storing auth secrets.
type Snapshot ¶
type Snapshot struct {
Version int `json:"version"`
Method string `json:"method"`
Path string `json:"path"`
Query map[string][]string `json:"query,omitempty"`
Headers map[string][]string `json:"headers,omitempty"`
RequestID string `json:"request_id,omitempty"`
RoutePattern string `json:"route_pattern,omitempty"`
RouteParams map[string]string `json:"route_params,omitempty"`
ApplicationVersion string `json:"application_version,omitempty"`
Environment string `json:"environment,omitempty"`
FeatureFlags map[string]string `json:"feature_flags,omitempty"`
ControlledBoundaries []Boundary `json:"controlled_boundaries,omitempty"`
UncontrolledBoundaries []Boundary `json:"uncontrolled_boundaries,omitempty"`
Principal *PrincipalRef `json:"principal,omitempty"`
CapturedAt time.Time `json:"captured_at"`
Body []byte `json:"body,omitempty"`
BodyOmitted bool `json:"body_omitted"`
ExpectedResponse *ExpectedResponse `json:"expected_response,omitempty"`
}
Snapshot captures enough request data to replay a handler request.