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 ¶
- type Expectation
- type Kind
- type MatchableRequest
- type RequestMatcher
- type ResponseDef
- type Store
- func (s *Store) DeleteByID(id string) bool
- func (s *Store) Find(method, concretePath, opTemplate string, req MatchableRequest) *Expectation
- func (s *Store) GetByID(id string) *Expectation
- func (s *Store) List() []Expectation
- func (s *Store) Put(exp Expectation) Expectation
- func (s *Store) ResetAll()
- func (s *Store) ResetEndpoint(method, path string, kind Kind)
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 MatchableRequest ¶
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 (*Store) DeleteByID ¶ added in v0.226.0
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:
- exact path, request matcher, newest
- exact path, catch-all, newest
- template path, request matcher, newest
- 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 ¶
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.