apitest

package
v1.7.2 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: BSD-2-Clause Imports: 10 Imported by: 0

Documentation

Overview

Package apitest serves a stand-in gonemaster-server for the CLI and tooling tests, over a real socket or in-process. It lives at the module root rather than under cmd/internal because tools/server-perf-kit is outside cmd/ and could not import it from there.

Index

Constants

View Source
const (
	DiffTagUnchanged = "B01_CHILD_FOUND"
	DiffTagRemoved   = "N11_NO_RESPONSE"
	DiffTagAdded     = "MULTIPLE_SOA_SERIALS"
	DiffTagChanged   = "ONE_SOA_SERIAL"
)

The tags of the run pair DiffPair returns, so a test can name what it expects rather than repeat a literal.

Variables

This section is empty.

Functions

func DiffResults

func DiffResults(idBefore, idAfter string) map[string]Result

DiffResults is DiffPair as two scored results keyed by run id, for the endpoints that serve a whole result rather than raw entries.

func Handler

func Handler(t testing.TB, opts Opts) http.Handler

Handler builds the fake's routes. Every request path is under /api/v1.

func JSONResponse

func JSONResponse(status int, body string) *http.Response

JSONResponse builds a canned JSON response, for use inside a RoundTripFunc.

func New

func New(t testing.TB, opts Opts) *httptest.Server

New starts the fake over a real socket and closes it when the test ends.

func StubClient

func StubClient(t testing.TB, seam *ClientFunc, rt http.RoundTripper)

StubClient points *seam at a client using rt and restores it at test end.

func StubFake

func StubFake(t testing.TB, seam *ClientFunc, opts Opts)

StubFake points *seam at the fake server's routes, with no socket.

func Transport

func Transport(t testing.TB, opts Opts) http.RoundTripper

Transport answers the fake's routes without a socket, for a client whose http.Client is injectable.

Types

type BatchCreateRequest

type BatchCreateRequest struct {
	Domains  []string `json:"domains,omitempty"`
	FromTag  string   `json:"from_tag,omitempty"`
	Profile  string   `json:"profile,omitempty"`
	Tags     []string `json:"tags,omitempty"`
	Tests    []string `json:"tests,omitempty"`
	MinLevel string   `json:"min_level,omitempty"`
}

BatchCreateRequest is the POST /jobs/batch payload the fake decodes.

type BatchCreateResponse

type BatchCreateResponse struct {
	BatchID string   `json:"batch_id"`
	JobIDs  []string `json:"job_ids"`
}

BatchCreateResponse is POST /jobs/batch.

type BatchList

type BatchList struct {
	Items []BatchListItem `json:"items"`
	Total int             `json:"total"`
}

BatchList is GET /batches.

type BatchListItem

type BatchListItem struct {
	BatchID     string     `json:"batch_id"`
	Tag         string     `json:"tag,omitempty"`
	Description string     `json:"description,omitempty"`
	Status      string     `json:"status"`
	Total       int        `json:"total"`
	Completed   int        `json:"completed"`
	Completion  int        `json:"completion"`
	CreatedAt   time.Time  `json:"created_at"`
	FinishedAt  *time.Time `json:"finished_at,omitempty"`
}

BatchListItem is one row of GET /batches.

type BatchSummary

type BatchSummary struct {
	BatchID      string         `json:"batch_id"`
	Tag          string         `json:"tag,omitempty"`
	Total        int            `json:"total"`
	StatusCounts map[string]int `json:"status_counts"`
	Grades       map[string]int `json:"grades,omitempty"`
	Items        []Job          `json:"items,omitempty"`
	Limit        int            `json:"limit,omitempty"`
	Offset       int            `json:"offset,omitempty"`
	NextCursor   string         `json:"next_cursor,omitempty"`
	CreatedAt    time.Time      `json:"created_at"`
	FinishedAt   *time.Time     `json:"finished_at,omitempty"`
}

BatchSummary is GET /batches/{id}.

type Capture

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

Capture is a RoundTripper that decodes each request body into a caller struct and answers with a canned JSON response, recording the method and path of the last request it served.

func CaptureJSON

func CaptureJSON(t testing.TB, into any, status int, body string) *Capture

CaptureJSON returns a Capture that decodes each request body into into (a pointer; nil skips the decode) and replies with status and body.

func (*Capture) Method

func (c *Capture) Method() string

Method returns the method of the last request served.

func (*Capture) Path

func (c *Capture) Path() string

Path returns the path of the last request served.

func (*Capture) RoundTrip

func (c *Capture) RoundTrip(r *http.Request) (*http.Response, error)

type ClientFunc

type ClientFunc = func(time.Duration) *http.Client

ClientFunc aliases the http.Client factory the CLIs expose as a seam, so *ClientFunc accepts a pointer to a package main var of that shape.

type Entry

type Entry struct {
	Timestamp float64        `json:"timestamp,omitempty"`
	Module    string         `json:"module"`
	Testcase  string         `json:"testcase"`
	Tag       string         `json:"tag"`
	Level     string         `json:"level"`
	Args      map[string]any `json:"args,omitempty"`
	Message   string         `json:"message,omitempty"`
}

Entry is one log entry of a raw result.

func DiffPair

func DiffPair() (before, after []Entry)

DiffPair is the before/after run the run-diff tests on both CLIs share: one tag unchanged, one gone, one new, and one whose severity rises. Every delta kind a diff reports appears exactly once, so a diff that misses a kind cannot pass.

type EntryList

type EntryList struct {
	Items []EntryRecord `json:"items"`
	Total int           `json:"total"`
}

EntryList is GET /entries.

type EntryRecord

type EntryRecord struct {
	Domain string `json:"domain"`
	Module string `json:"module"`
	Tag    string `json:"tag"`
	Level  string `json:"level"`
}

EntryRecord is one row of GET /entries.

type Job

type Job struct {
	ID         string    `json:"id"`
	BatchID    string    `json:"batch_id,omitempty"`
	Domain     string    `json:"domain"`
	Status     string    `json:"status"`
	Progress   int       `json:"progress"`
	Error      string    `json:"error,omitempty"`
	CreatedAt  time.Time `json:"created_at"`
	StartedAt  time.Time `json:"started_at"`
	FinishedAt time.Time `json:"finished_at"`
}

Job is a job from POST /jobs and GET /jobs/{id}.

type NSTiming

type NSTiming struct {
	Nameserver   string  `json:"nameserver"`
	Address      string  `json:"address"`
	AvgMS        float64 `json:"avg_ms"`
	MinMS        float64 `json:"min_ms"`
	MaxMS        float64 `json:"max_ms"`
	MedianMS     float64 `json:"median_ms"`
	Count        int     `json:"count"`
	Status       string  `json:"status"`
	TimeoutCount int     `json:"timeout_count,omitempty"`
	RefusedCount int     `json:"refused_count,omitempty"`
}

NSTiming is one row of nameserver_timings.

type Opts

type Opts struct {
	// RequireToken, when set, makes every route answer 401 unless the
	// request carries the matching Bearer token.
	RequireToken string
	// WhoamiMode selects the GET /whoami answer: "open" reports
	// authenticated, "token" reports authenticated only for RequireToken.
	WhoamiMode string

	// PollsUntilDone keeps GET /jobs/{id} on "running" for that many polls.
	PollsUntilDone int
	// FinalStatus is the terminal job status, "succeeded" when empty.
	FinalStatus string
	// JobError is job.error at the terminal poll.
	JobError string

	// Result answers GET /jobs|runs/{id}/result; nil yields 404.
	Result *Result
	// ResultsByID answers per id and is consulted before Result.
	ResultsByID map[string]Result

	// Run answers GET /runs/{id}; nil yields 404.
	Run *Run
	// Runs are the items of GET /runs, paged when the query asks for it.
	Runs []Run
	// RunsQuery, when set, captures the GET /runs query of every request.
	RunsQuery *url.Values
	// RunsRequests, when set, records the raw query of every GET /runs.
	RunsRequests *[]string

	// Batch answers GET /batches/{id}; nil yields 404.
	Batch *BatchSummary
	// BatchesByID answers per id and is consulted before Batch.
	BatchesByID map[string]BatchSummary
	// BatchList answers GET /batches.
	BatchList *BatchList
	// BatchListQuery, when set, captures the GET /batches query.
	BatchListQuery *url.Values
	// TagValues answers GET /batches/{id}/tag-values; nil yields 404.
	TagValues *TagValues
	// TagValuesQuery, when set, captures the tag-values query.
	TagValuesQuery *url.Values
	// BatchReq, when set, captures the POST /jobs/batch body.
	BatchReq *BatchCreateRequest

	// Entries are the items of GET /entries, filtered by the level query.
	Entries []EntryRecord

	// SpecList answers GET /spec/testcases.
	SpecList *SpecTestcaseList
	// SpecDetail answers GET /spec/testcases/{id}; nil yields 404.
	SpecDetail *SpecTestcaseDetail
}

Opts is the fake server's canned state. A zero Opts answers every route with an empty or not-found body.

type Result

type Result struct {
	JobID             string         `json:"job_id"`
	BatchID           string         `json:"batch_id,omitempty"`
	Status            string         `json:"status"`
	Summary           map[string]any `json:"summary,omitempty"`
	Raw               *ResultRaw     `json:"raw,omitempty"`
	Score             *Score         `json:"score,omitempty"`
	NameserverTimings []NSTiming     `json:"nameserver_timings,omitempty"`
}

Result is GET /jobs/{id}/result and the identical /runs/{id}/result.

type ResultRaw

type ResultRaw struct {
	Locale  string  `json:"locale,omitempty"`
	Entries []Entry `json:"entries"`
}

ResultRaw is the raw entry list inside a result.

type RoundTripFunc

type RoundTripFunc func(*http.Request) (*http.Response, error)

RoundTripFunc adapts a function to http.RoundTripper, for the tests that need a handler of their own rather than the fake.

func (RoundTripFunc) RoundTrip

func (fn RoundTripFunc) RoundTrip(r *http.Request) (*http.Response, error)

type Run

type Run struct {
	ID         string    `json:"id"`
	Domain     string    `json:"domain"`
	BatchID    string    `json:"batch_id,omitempty"`
	PublicID   string    `json:"public_id,omitempty"`
	Status     string    `json:"status"`
	DurationMs int64     `json:"duration_ms"`
	WorstLevel string    `json:"worst_level,omitempty"`
	Score      *int      `json:"score"`
	Grade      *string   `json:"grade"`
	FinishedAt time.Time `json:"finished_at"`
	Error      string    `json:"error,omitempty"`
}

Run is a run from GET /runs and GET /runs/{id}.

type RunList

type RunList struct {
	Items []Run `json:"items"`
	Total int   `json:"total"`
}

RunList is GET /runs.

type Score

type Score struct {
	Score int    `json:"score"`
	Grade string `json:"grade"`
}

Score is the scoring block of a result.

type SpecTag

type SpecTag struct {
	Tag     string `json:"tag"`
	Message string `json:"message"`
}

SpecTag is one tag of a testcase detail.

type SpecTestcase

type SpecTestcase struct {
	ID          string `json:"id"`
	Module      string `json:"module"`
	Description string `json:"description"`
}

SpecTestcase is one item of GET /spec/testcases.

type SpecTestcaseDetail

type SpecTestcaseDetail struct {
	ID          string    `json:"id"`
	Module      string    `json:"module"`
	Description string    `json:"description"`
	Locale      string    `json:"locale"`
	Tags        []SpecTag `json:"tags"`
}

SpecTestcaseDetail is GET /spec/testcases/{id}.

type SpecTestcaseList

type SpecTestcaseList struct {
	Items []SpecTestcase `json:"items"`
	Total int            `json:"total"`
}

SpecTestcaseList is GET /spec/testcases.

type TagValue

type TagValue struct {
	Value         string   `json:"value"`
	Count         int      `json:"count"`
	AvgScore      *float64 `json:"avg_score,omitempty"`
	SampleDomains []string `json:"sample_domains"`
}

TagValue is one row of GET /batches/{id}/tag-values.

type TagValues

type TagValues struct {
	BatchID       string     `json:"batch_id"`
	Tag           string     `json:"tag"`
	Arg           string     `json:"arg"`
	MinCount      int        `json:"min_count"`
	WeightByScore bool       `json:"weight_by_score,omitempty"`
	Values        []TagValue `json:"values"`
}

TagValues is GET /batches/{id}/tag-values.

type Whoami

type Whoami struct {
	Mode          string `json:"mode"`
	Authenticated bool   `json:"authenticated"`
}

Whoami is GET /whoami.

Jump to

Keyboard shortcuts

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