matches

package
v0.229.0 Latest Latest
Warning

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

Go to latest
Published: May 27, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package matches owns the in-memory store of registered mock expectations.

An Expectation pairs an optional request matcher with a canned HTTP response, keyed by method and path. Paths can be concrete (e.g. "/api/v2/users/auth0|123") or OpenAPI templates (e.g. "/api/v2/users/{id}").

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Expectation

type Expectation struct {
	ID       string          `json:"id,omitempty"`
	Method   string          `json:"method"`
	Path     string          `json:"path"`
	Kind     Kind            `json:"-"`
	Request  *RequestMatcher `json:"request,omitempty"`
	Response ResponseDef     `json:"response"`
	Hits     int64           `json:"hits"`
}

Expectation is a stored mock response, optionally conditioned on the incoming request via Request. A nil Request is a catch-all.

ID is assigned by the store on Put() — callers leave it empty on registration and read it back from POST /admin0/expectations or GET /admin0/expectations. It uniquely identifies this expectation for the lifetime of the mock process; re-registering the same (method, path, matcher) tuple generates a fresh ID and supersedes the prior one.

Hits is populated by List() and GetByID() from the store's per-ID atomic counter — every match served by Find() increments it by one. Callers leave Hits zero on Put(); the counter starts at 0 and is reset when the expectation is removed.

type Kind

type Kind int

Kind distinguishes how an Expectation's path is interpreted.

const (
	// KindExact means the registration was made with a concrete URL path.
	KindExact Kind = iota
	// KindTemplate means the registration was made with an OpenAPI path template.
	KindTemplate
)

func KindOf

func KindOf(path string) Kind

KindOf reports whether path is a concrete URL (KindExact) or an OpenAPI path template containing a "{...}" segment (KindTemplate).

type MatchableRequest

type MatchableRequest struct {
	Query   url.Values
	Headers http.Header
	Body    []byte
}

MatchableRequest carries the parts of an incoming request that a RequestMatcher is compared against.

type RequestMatcher

type RequestMatcher struct {
	Query   map[string]string `json:"query,omitempty"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    json.RawMessage   `json:"body,omitempty"`
}

RequestMatcher is the optional set of conditions an incoming request must satisfy for an Expectation to apply.

Headers are compared case-insensitively (canonical-MIME-header form), and subset-matched: every header in the matcher must be present with an equal value, but extra headers on the incoming request don't disqualify a match. Useful for stubbing different responses based on Authorization (Bearer vs DPoP), Accept-Language, Tenant-Id, etc.

func (*RequestMatcher) IsEmpty

func (rm *RequestMatcher) IsEmpty() bool

IsEmpty reports whether the matcher carries no criteria. An empty matcher is equivalent to a nil catch-all and is normalized to nil on registration.

func (*RequestMatcher) Matches

func (rm *RequestMatcher) Matches(req MatchableRequest) bool

Matches reports whether req satisfies the matcher. A nil matcher (catch-all) always matches. Query and header keys are subset-matched (every matcher key must be present with an equal value; extras are allowed); the body is subset-matched via subsetMatch.

Header lookup is case-insensitive — http.Header.Get canonicalises the key against the canonical MIME header form, so a matcher entry "X-Tenant: acme" matches an incoming header named "x-tenant" or "X-TENANT".

type ResponseDef

type ResponseDef struct {
	Status  int               `json:"status"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    json.RawMessage   `json:"body,omitempty"`
}

ResponseDef is the canned response an Expectation returns.

type Store

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

Store holds registered Expectation entries in memory as an ordered list (oldest to newest) per (method, path) key. Safe for concurrent use.

Hits is an independent map of per-ID atomic counters — kept off Expectation itself because Expectation is passed by value and atomically-incremented fields on a copy are meaningless. Read via hits[id].Load(), written via hits[id].Add(1), guarded against concurrent map mutation by mu (only Put / DeleteByID / ResetAll touch the map shape).

func NewStore

func NewStore() *Store

NewStore returns an empty Store.

func (*Store) DeleteByID added in v0.226.0

func (s *Store) DeleteByID(id string) bool

DeleteByID removes the expectation with the given id from any bucket and drops its hit counter. Returns true if an entry was removed, false if no expectation with that id existed (idempotent — callers don't need to pre-check).

func (*Store) Find

func (s *Store) Find(method, concretePath, opTemplate string, req MatchableRequest) *Expectation

Find returns the Expectation that should serve (method, concretePath) given the incoming request. It considers the exact-path list and the template list registered against opTemplate, keeps only entries whose Request matches req, and applies a 4-tier precedence:

  1. exact path, request matcher, newest
  2. exact path, catch-all, newest
  3. template path, request matcher, newest
  4. template path, catch-all, newest

Returns nil when nothing matches. Also atomically increments the matched expectation's hit counter — the returned *Expectation carries the post-increment Hits value so callers can log "served call #N" without a second lookup.

func (*Store) GetByID added in v0.226.0

func (s *Store) GetByID(id string) *Expectation

GetByID returns the expectation with the given id (a copy) with its current Hits populated, or nil if no such expectation exists.

func (*Store) List

func (s *Store) List() []Expectation

List returns every registered Expectation, sorted by (method, path), with each entry's Hits populated from the store's per-ID counter.

func (*Store) Put

func (s *Store) Put(exp Expectation) Expectation

Put inserts exp into its (method, path) list. If an entry with an equal Request matcher already exists for that key it is removed first, so the re-registered expectation becomes the newest. The path is treated as exact or template based on exp.Kind.

Generates a fresh UUID for exp.ID before storing — any inbound ID on exp is overwritten so callers can't forge or reuse IDs. Returns the stored Expectation (carrying the assigned ID) so callers can hand it to the network layer without re-locking.

func (*Store) ResetAll

func (s *Store) ResetAll()

ResetAll clears every registered Expectation and its hit counter.

func (*Store) ResetEndpoint

func (s *Store) ResetEndpoint(method, path string, kind Kind)

ResetEndpoint removes every Expectation keyed by (method, path) within the map indicated by kind, dropping each expectation's hit counter too. Calls for unregistered keys are no-ops.

Jump to

Keyboard shortcuts

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