scenario

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 36 Imported by: 0

Documentation

Overview

Package scenario defines the Stampede scenario file format: its types, parsing, validation and the templating used inside steps.

Index

Constants

View Source
const (
	ExtractJSON   = "json"
	ExtractHeader = "header"
	ExtractCookie = "cookie"
	ExtractRegex  = "regex"
	ExtractCSS    = "css"
	ExtractStatus = "status"
	ExtractBody   = "body"
)

Extractor kinds.

View Source
const (
	ExecConstantVUs  = "constant-vus"
	ExecRampingVUs   = "ramping-vus"
	ExecConstantRate = "constant-rate"
	ExecRampingRate  = "ramping-rate"
	ExecIterations   = "iterations"
)

Executor names.

View Source
const (
	MetricP50     = "p50"
	MetricP90     = "p90"
	MetricP95     = "p95"
	MetricP99     = "p99"
	MetricP999    = "p99.9"
	MetricMax     = "max"
	MetricMean    = "mean"
	MetricErrors  = "errors"
	MetricChecks  = "checks"
	MetricDropped = "dropped"
	MetricRPS     = "rps"
	MetricCount   = "count"
)

Metric names that thresholds can refer to.

View Source
const (
	FeedSequential = "sequential"
	FeedUnique     = "unique"
	FeedRandom     = "random"
	FeedPerVU      = "per-vu"
)

Feeder modes.

View Source
const (
	ModeVUs  = "vus"
	ModeRate = "rate"
)

Load modes.

View Source
const APIVersion = "stampede.dev/v1"

APIVersion is the scenario format version this build reads and writes.

View Source
const ExecReplay = "replay"

ExecReplay is the executor of replay plans.

View Source
const KindScenario = "Scenario"

KindScenario is the only document kind currently defined.

View Source
const (
	MaxObserveQueries = 20
)

Limits on the observe block.

View Source
const MaxReplaySpan = 7 * 24 * time.Hour

MaxReplaySpan is the longest a replay may last, after speed.

View Source
const ModeReplay = "replay"

ModeReplay replays a recorded arrival pattern (load.mode: replay).

View Source
const ScopeAll = "http"

ScopeAll is the threshold scope that covers every request.

View Source
const TraceIDPlaceholder = "{traceId}"

TraceIDPlaceholder is replaced by a trace ID in trace link templates.

Variables

View Source
var (

	// IntegrationNameRe matches the names of server integrations and
	// notification channels.
	IntegrationNameRe = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_.-]{0,99}$`)
)
View Source
var Shapes = []string{"smoke", "baseline", "stress", "spike", "soak", "breakpoint", "steps", "recovery", "wave"}

Shapes lists the traffic shape presets.

Functions

func CheckTraceURL

func CheckTraceURL(tmpl string) string

CheckTraceURL validates a trace link template and returns a problem, or "" when it is usable.

func FormatMetric

func FormatMetric(metric string, v float64) string

FormatMetric renders a value in a metric's natural unit.

func GRPCCodeName

func GRPCCodeName(s string) (string, bool)

GRPCCodeName returns the canonical name of a gRPC status code given in any case, with or without underscores (NOT_FOUND, NotFound, not_found).

func IsAbsoluteURL

func IsAbsoluteURL(s string) bool

IsAbsoluteURL reports whether a step URL names its own scheme and host, rather than a path joined to target.baseURL.

func IsReserved

func IsReserved(name string) bool

IsReserved reports whether name is a built-in expression variable and so cannot be used as an extracted variable name.

func JSONPathToGJSON

func JSONPathToGJSON(p string) (string, error)

JSONPathToGJSON converts the JSONPath subset Stampede accepts into a gjson path. Supported: $, .key, ['key'], ["key"], [n], [*] and .length.

$.items[0].id      -> items.0.id
$.items[*].id      -> items.#.id
$['odd key'].x     -> odd key.x (escaped)
$.items.length     -> items.#

func PathTemplate

func PathTemplate(p string) string

PathTemplate replaces ids in a path with placeholders: /api/orders/42/items/9f1c... becomes /api/orders/{id}/items/{hex}.

func StepURL

func StepURL(st Step) (u string, ok bool)

StepURL returns where a step sends traffic as written (templates not rendered): the URL of an HTTP, GraphQL, SSE, WebSocket or browser step or a goto action, or a gRPC step's target. ok is false for steps that send nothing or use the target's base URL implicitly.

func Stringify

func Stringify(v any) string

Stringify formats an evaluated value for interpolation into text.

func ToNative

func ToNative(v ref.Val) any

ToNative converts a CEL value into plain Go values (string, int64, float64, bool, nil, []any, map[string]any).

func TraceLink(tmpl, traceID string) string

TraceLink fills a trace link template with a trace ID.

func ValidateRegions

func ValidateRegions(regions map[string]Percent) []string

ValidateRegions checks a region split: known-looking names, every share above zero and a total of 100%.

func WalkSteps

func WalkSteps(steps []Step, fn func(Step))

WalkSteps calls fn for every step in steps, nested ones included.

Types

type Abort

type Abort struct {
	// Errors is the failed-request ratio that trips the abort.
	Errors *Percent `yaml:"errors,omitempty" json:"errors,omitempty"`
	// P95 is the latency that trips the abort.
	P95 Duration `yaml:"p95,omitempty" json:"p95,omitempty"`
	// For is how long the limit must be exceeded (default 10s).
	For Duration `yaml:"for,omitempty" json:"for,omitempty"`
}

Abort ends a run when errors or latency stay above a limit for a while, so a broken target is not hammered for the rest of the test.

type Arrival

type Arrival struct {
	At       time.Duration // since the first request, after Speed
	Endpoint int
	// Target is the path and query to request.
	Target      string
	Body        string
	ContentType string
}

Arrival is one recorded request.

type Branch

type Branch struct {
	Weight int    `yaml:"weight" json:"weight"`
	Name   string `yaml:"name,omitempty" json:"name,omitempty"`
	Steps  []Step `yaml:"steps" json:"steps"`
}

Branch is one weighted alternative inside a branch step.

type Browser

type Browser struct {
	URL string
	// Timeout bounds each action (default the target timeout).
	Timeout  Duration
	Viewport *Viewport
	Steps    []Step
}

Browser opens URL in a browser page as one virtual user would, then runs Steps (browser actions) in that page.

type BrowserAction

type BrowserAction struct {
	Target  string
	Pairs   []SelectorValue
	Timeout Duration
}

BrowserAction is one action in a browser page. Target is the URL for goto, the CSS selector for click and waitFor, and the key for press. Pairs map selectors to values for fill (text to type) and assert (text the element must contain), in order.

type CAction

type CAction struct {
	Target  *Template
	Pairs   []CSelectorValue
	Timeout Duration
}

CAction is a compiled browser action.

type CBranch

type CBranch struct {
	Weight int
	Name   string
	Steps  []*CStep
}

CBranch is one weighted alternative.

type CBrowser

type CBrowser struct {
	URL      *Template
	Timeout  Duration
	Viewport Viewport
}

CBrowser is a compiled browser block: the page is opened at URL and the block's Steps (actions) run in it.

type CCheck

type CCheck struct {
	Status       StatusMatcher
	BodyContains *Template
	JSON         []JSONCheck
	MaxLatency   Duration
	Expr         *Expr
	// Schema validates the body; see SchemaProblem.
	Schema *jsonschema.Schema
	// NeedsJSON is set when the check reads the parsed body.
	NeedsJSON bool
}

CCheck is a compiled response check.

func (*CCheck) SchemaProblem

func (c *CCheck) SchemaProblem(body []byte) string

SchemaProblem validates body against the check's schema and returns "" when it passes, or the first problem.

type CExpect

type CExpect struct {
	Match   *regexp.Regexp
	JSON    []JSONCheck
	Timeout Duration
	Extract []Extractor
}

CExpect is a compiled wait for a WebSocket message.

type CGRPC

type CGRPC struct {
	// Service is the service's full name and Method the method's name.
	Service string
	Method  string
	// Target is nil when calls go to target.baseURL's host.
	Target      *Template
	Message     *JSONTemplate
	Metadata    []KV
	Protoset    string
	Proto       []string
	ImportPaths []string
	// Codes are the accepted status code names (canonical, such as
	// NOT_FOUND); CheckedStatus is set when the scenario listed them.
	Codes         []string
	CheckedStatus bool
}

CGRPC is a compiled gRPC call.

type CGraphQL

type CGraphQL struct {
	// Query is nil when only a persisted query hash is sent.
	Query         *Template
	Variables     *JSONTemplate
	OperationName string
	Persisted     bool
	// Hash is the persisted query's SHA-256 in hex when it is known at
	// compile time; empty means hash the rendered query.
	Hash        string
	AllowErrors bool
}

CGraphQL is a compiled GraphQL operation.

type CJourney

type CJourney struct {
	Index  int
	Name   string
	Weight int
	Steps  []*CStep
}

CJourney is a compiled journey.

type CLoop

type CLoop struct {
	Count int
	Cond  *Expr
	Max   int
}

CLoop holds loop parameters; the body is CStep.Steps.

type CPlugin

type CPlugin struct {
	// Plugin and Step split "mqtt.publish".
	Plugin, Step string
	// With renders the step's config.
	With *JSONTemplate
	// Config is the config as written, for checking it against the
	// plugin's schema; Templated lists the JSON pointers of its strings
	// that contain ${} expressions, whose type is only known at run time.
	Config    map[string]any
	Templated []string
}

CPlugin is a compiled plugin step.

type CRequest

type CRequest struct {
	Method  string
	URL     *Template
	Headers []KV
	Query   []KV
	JSON    *JSONTemplate
	Body    *Template
	Form    []KV
	Check   *CCheck
	Extract []Extractor
	Timeout Duration
}

CRequest is a compiled HTTP request.

type CSSE

type CSSE struct {
	Events   int
	Match    *regexp.Regexp
	Duration Duration
}

CSSE says when a compiled server-sent events step stops reading.

type CSelectorValue

type CSelectorValue struct {
	Selector, Value *Template
}

CSelectorValue is a selector and its value, both templates.

type CSend

type CSend struct {
	Text *Template
	JSON *JSONTemplate
}

CSend is a compiled WebSocket message: exactly one of Text and JSON.

type CStep

type CStep struct {
	ID      int
	Kind    StepKind
	Name    string
	Journey string
	If      *Expr

	Req      *CRequest
	Think    *ThinkTime
	Branches []CBranch
	// BranchTotal is the sum of branch weights.
	BranchTotal int
	Loop        *CLoop
	Group       string
	Steps       []*CStep

	// GraphQL and SSE are set for their step kinds, whose HTTP parts are
	// in Req.
	GraphQL *CGraphQL
	SSE     *CSSE
	// WS is set for ws steps: Req holds the handshake and Steps run on
	// the connection.
	WS *CWS
	// Browser is set for browser steps, whose Steps run in the page;
	// Action for the actions inside them.
	Browser *CBrowser
	Action  *CAction
	Send    *CSend
	Expect  *CExpect
	// GRPC is set for grpc steps; Req holds their check (without status),
	// extractors and timeout.
	GRPC *CGRPC
	// Script is set for script steps.
	Script *script.Program
	// Plugin is set for plugin steps; Req holds their check, extractors
	// and timeout.
	Plugin *CPlugin
}

CStep is a compiled step.

type CWS

type CWS struct {
	Subprotocols []string
}

CWS is a compiled WebSocket block.

type Check

type Check struct {
	// Status accepts exact codes (200), lists ([200, 201]) or classes ("2xx").
	Status       StatusMatcher `yaml:"status,omitempty" json:"status,omitempty"`
	BodyContains string        `yaml:"bodyContains,omitempty" json:"bodyContains,omitempty"`
	// JSON maps a JSONPath to the expected value. The special value
	// "exists" only requires the path to be present.
	JSON       map[string]any `yaml:"json,omitempty" json:"json,omitempty"`
	MaxLatency Duration       `yaml:"maxLatency,omitempty" json:"maxLatency,omitempty"`
	// Expr is a boolean expression over status, headers, body and json.
	Expr string `yaml:"expr,omitempty" json:"expr,omitempty"`
	// Schema validates the JSON body against a JSON Schema (draft 2020-12
	// unless the schema says otherwise): an inline object, or the path of
	// a .json, .yaml or .yml file relative to the scenario.
	Schema any `yaml:"schema,omitempty" json:"schema,omitempty"`
	// AllowErrors (GraphQL only) accepts a response whose errors array is
	// not empty; by default that fails the step.
	AllowErrors bool `yaml:"allowErrors,omitempty" json:"allowErrors,omitempty"`
}

Check asserts on a response. Failed checks count as errors.

type Duration

type Duration time.Duration

Duration is a time.Duration that reads "500ms", "2s", "1m30s", "4h" or "2d" from YAML/JSON, and treats a bare number as seconds.

func ParseDuration

func ParseDuration(s string) (Duration, error)

ParseDuration parses a Stampede duration string.

func (Duration) D

func (d Duration) D() time.Duration

D returns the value as a time.Duration.

func (Duration) MarshalJSON

func (d Duration) MarshalJSON() ([]byte, error)

func (Duration) MarshalYAML

func (d Duration) MarshalYAML() (any, error)

func (Duration) String

func (d Duration) String() string

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(b []byte) error

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(n *yaml.Node) error

type Endpoint

type Endpoint struct {
	Method   string
	Template string
	HasBody  bool
	Count    int
}

Endpoint is one method and path template, e.g. GET /api/products/{id}.

func (Endpoint) JourneyName

func (ep Endpoint) JourneyName() string

JourneyName names the endpoint's journey. Journey names cannot hold '/', so GET /api/products/{id} becomes "GET api.products.{id}".

type Expect

type Expect struct {
	// Match is a regex over the message.
	Match string `yaml:"match,omitempty" json:"match,omitempty"`
	// JSON maps a JSONPath to the expected value, or "exists".
	JSON    map[string]any `yaml:"json,omitempty" json:"json,omitempty"`
	Timeout Duration       `yaml:"timeout,omitempty" json:"timeout,omitempty"`
	// Extract reads variables from the matching message.
	Extract map[string]string `yaml:"-" json:"-"`
}

Expect waits for a message that matches every condition given; other messages are skipped. With no condition the next message matches.

type Expr

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

Expr is a compiled expression.

func (*Expr) Eval

func (e *Expr) Eval(vars interpreter.Activation) (any, error)

Eval evaluates the expression against vars.

func (*Expr) EvalBool

func (e *Expr) EvalBool(vars interpreter.Activation) (bool, error)

EvalBool evaluates a condition.

func (*Expr) String

func (e *Expr) String() string

String returns the expression source.

type Extractor

type Extractor struct {
	Var  string
	Kind string
	Src  string
	// GJSON path for json extractors.
	GJSON string
	Regex *regexp.Regexp
	CSS   cascadia.Sel
	// Attr is the attribute read by CSS extractors (text when empty).
	Attr string
}

Extractor pulls a value out of a response into a variable.

func ParseExtractor

func ParseExtractor(name, rule string) (Extractor, error)

ParseExtractor parses an extraction rule:

$.path            JSONPath into the response body
header:Name       response header
cookie:name       cookie set by the response
regex:pattern     first capture group (or whole match) in the body
css:selector      text of the first match; css:selector@attr for an attribute
status | body     the status code or the whole body

type FaultAgent

type FaultAgent struct {
	URL         string `yaml:"url,omitempty" json:"url,omitempty"`
	Token       string `yaml:"token,omitempty" json:"token,omitempty"`
	Integration string `yaml:"integration,omitempty" json:"integration,omitempty"`
}

FaultAgent is where the agent's control API is. With stampede run, set URL and Token (both may be templated, for example ${env.AGENT_URL} and ${secret.AGENT_TOKEN}). On a server, name an agent integration instead: the server only contacts URLs an admin configured.

type FaultStep

type FaultStep struct {
	Name string   `yaml:"name,omitempty" json:"name,omitempty"`
	At   Duration `yaml:"at" json:"at"`
	For  Duration `yaml:"for" json:"for"`

	// Proxy names one of the agent's proxies.
	Proxy     string   `yaml:"proxy,omitempty" json:"proxy,omitempty"`
	Latency   Duration `yaml:"latency,omitempty" json:"latency,omitempty"`
	Jitter    Duration `yaml:"jitter,omitempty" json:"jitter,omitempty"`
	Bandwidth string   `yaml:"bandwidth,omitempty" json:"bandwidth,omitempty"`
	Reset     bool     `yaml:"reset,omitempty" json:"reset,omitempty"`
	Refuse    bool     `yaml:"refuse,omitempty" json:"refuse,omitempty"`
	Blackhole bool     `yaml:"blackhole,omitempty" json:"blackhole,omitempty"`

	// Container is a Docker container; Action is pause, stop, kill or
	// restart.
	Container string `yaml:"container,omitempty" json:"container,omitempty"`
	Action    string `yaml:"action,omitempty" json:"action,omitempty"`

	// Deployment is a Kubernetes deployment (namespace/name) scaled to
	// Replicas.
	Deployment string `yaml:"deployment,omitempty" json:"deployment,omitempty"`
	Replicas   *int   `yaml:"replicas,omitempty" json:"replicas,omitempty"`
}

FaultStep is one fault: what to break, from At (after the load starts) for For. Set exactly one of Proxy, Container or Deployment.

func (FaultStep) Label

func (f FaultStep) Label() string

Label names the fault in reports: Name, or a description of it.

type Faults

type Faults struct {
	Agent    FaultAgent  `yaml:"agent" json:"agent"`
	Timeline []FaultStep `yaml:"timeline" json:"timeline"`
}

Faults is a timeline of faults injected by a stampede agent.

type Feeder

type Feeder struct {
	CSV  string `yaml:"csv,omitempty" json:"csv,omitempty"`
	JSON string `yaml:"json,omitempty" json:"json,omitempty"`
	List []any  `yaml:"list,omitempty" json:"list,omitempty"`
	// Range generates integers from Range[0] to Range[1] inclusive.
	Range []int64 `yaml:"range,omitempty" json:"range,omitempty"`
	// Generate makes a fresh row of fake data for every use: field name to
	// kind, such as email, name, uuid, int(1,100) or text(5MB). Mode and
	// OnExhausted do not apply.
	Generate map[string]string `yaml:"generate,omitempty" json:"generate,omitempty"`
	// SQL reads rows from a database query when the run starts.
	SQL *SQLFeeder `yaml:"sql,omitempty" json:"sql,omitempty"`
	// Mode is one of unique, sequential, random or per-vu (default sequential).
	Mode string `yaml:"mode,omitempty" json:"mode,omitempty"`
	// OnExhausted applies to unique mode: "stop" ends the virtual user,
	// "wrap" starts again from the first row (default stop).
	OnExhausted string `yaml:"onExhausted,omitempty" json:"onExhausted,omitempty"`
}

Feeder supplies test data rows to virtual users.

type GRPC

type GRPC struct {
	// Method is "package.Service/Method".
	Method string
	// Target is grpc://host:port or grpcs://host:port; empty means the
	// host of target.baseURL (TLS for https). It may use env, secret and
	// vars, which are rendered once when the run starts.
	Target string
	// Message is the request as JSON (protojson field names); strings may
	// contain ${} expressions.
	Message  any
	Metadata map[string]string
	// Descriptors come from server reflection unless Protoset (a
	// FileDescriptorSet) or Proto (source files, found under ImportPaths)
	// is set.
	Protoset    string
	Proto       []string
	ImportPaths []string
	Check       *GRPCCheck
	Extract     map[string]string
	Timeout     Duration
}

GRPC calls a unary or server-streaming gRPC method.

type GRPCCheck

type GRPCCheck struct {
	Status     GRPCCodes      `yaml:"status,omitempty" json:"status,omitempty"`
	JSON       map[string]any `yaml:"json,omitempty" json:"json,omitempty"`
	MaxLatency Duration       `yaml:"maxLatency,omitempty" json:"maxLatency,omitempty"`
	Expr       string         `yaml:"expr,omitempty" json:"expr,omitempty"`
}

GRPCCheck asserts on a gRPC response. Status lists the accepted status codes by name (default OK); the rest work as for HTTP, on the response rendered as JSON.

type GRPCCodes

type GRPCCodes []string

GRPCCodes is one status code name or a list of them.

func (*GRPCCodes) UnmarshalYAML

func (c *GRPCCodes) UnmarshalYAML(n *yaml.Node) error

UnmarshalYAML accepts one code name or a list.

type GraphQL

type GraphQL struct {
	Request
	Query         string
	Variables     any
	OperationName string
	// Persisted sends an automatic persisted query (APQ): the query's
	// SHA-256 first, and the full query only if the server does not know it.
	Persisted *Persisted
}

GraphQL is a GraphQL operation sent as an HTTP POST. Request holds the endpoint, headers, check, extract and timeout.

type Group

type Group struct {
	Name  string
	Steps []Step
}

Group names a set of steps so they are reported together.

type HTTPOptions

type HTTPOptions struct {
	// Connections is "per-vu" (each virtual user keeps its own keep-alive
	// connections, like browsers; the default) or "shared" (one pool for
	// all users, like a service client).
	Connections string `yaml:"connections,omitempty" json:"connections,omitempty"`
	// HTTP2 enables HTTP/2 over TLS when the server offers it.
	HTTP2 bool `yaml:"http2,omitempty" json:"http2,omitempty"`
	// H2C speaks HTTP/2 without TLS to http:// targets, with prior
	// knowledge rather than an upgrade from HTTP/1.1.
	H2C bool `yaml:"h2c,omitempty" json:"h2c,omitempty"`
	// DisableKeepAlive opens a new connection for every request.
	DisableKeepAlive bool `yaml:"disableKeepAlive,omitempty" json:"disableKeepAlive,omitempty"`
	// InsecureSkipVerify disables TLS certificate checks (test targets only).
	InsecureSkipVerify bool `yaml:"insecureSkipVerify,omitempty" json:"insecureSkipVerify,omitempty"`
	// DNSCacheTTL is how long a host name lookup is reused across
	// connections (default 30s). Set "0s" to resolve on every connection.
	DNSCacheTTL *Duration `yaml:"dnsCacheTTL,omitempty" json:"dnsCacheTTL,omitempty"`
	// MaxRedirects caps followed redirects (default 10, 0 keeps the default,
	// -1 disables following).
	MaxRedirects int `yaml:"maxRedirects,omitempty" json:"maxRedirects,omitempty"`
	// TLSResumption is "per-vu" (each user resumes only its own TLS
	// sessions, like separate browsers; the default with per-vu
	// connections), "shared" (any user resumes any session; the default
	// with shared connections) or "off" (a full handshake on every new
	// connection).
	TLSResumption string `yaml:"tlsResumption,omitempty" json:"tlsResumption,omitempty"`
}

HTTPOptions tunes connection behaviour so it resembles real clients.

type JSONCheck

type JSONCheck struct {
	Path     string // original JSONPath
	GJSON    string
	Exists   bool
	Expected any
}

JSONCheck asserts a value at a path.

type JSONTemplate

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

JSONTemplate is a JSON value whose strings may contain templates.

func (*JSONTemplate) Source

func (j *JSONTemplate) Source() string

Source returns every template source in the JSON value, joined by newlines, for static analysis such as finding referenced feeders.

func (*JSONTemplate) Value

func (j *JSONTemplate) Value(vars interpreter.Activation) (any, error)

Value evaluates the JSON template into plain Go values.

type Journey

type Journey struct {
	Name   string       `yaml:"name" json:"name"`
	Weight int          `yaml:"weight,omitempty" json:"weight,omitempty"`
	Tags   []string     `yaml:"tags,omitempty" json:"tags,omitempty"`
	Target *JourneyGoal `yaml:"target,omitempty" json:"target,omitempty"`
	Steps  []Step       `yaml:"steps" json:"steps"`
}

Journey is one path a user takes through the product.

type JourneyGoal

type JourneyGoal struct {
	P50    Duration `yaml:"p50,omitempty" json:"p50,omitempty"`
	P90    Duration `yaml:"p90,omitempty" json:"p90,omitempty"`
	P95    Duration `yaml:"p95,omitempty" json:"p95,omitempty"`
	P99    Duration `yaml:"p99,omitempty" json:"p99,omitempty"`
	Errors *Percent `yaml:"errors,omitempty" json:"errors,omitempty"`
}

JourneyGoal is a per-journey target, stricter or looser than the global one.

type KV

type KV struct {
	Name  string
	Value *Template
}

KV is a templated name/value pair.

type Load

type Load struct {
	// Shape picks a preset (smoke, baseline, stress, spike, soak,
	// breakpoint, steps, recovery, wave). Explicit Stages override it.
	Shape string `yaml:"shape,omitempty" json:"shape,omitempty"`
	// Mode is "rate" (open model: start journeys on a schedule) or "vus"
	// (closed model: a fixed population loops). Default vus.
	Mode string `yaml:"mode,omitempty" json:"mode,omitempty"`

	VUs      int      `yaml:"vus,omitempty" json:"vus,omitempty"`
	Rate     Rate     `yaml:"rate,omitempty" json:"rate,omitempty"`
	Duration Duration `yaml:"duration,omitempty" json:"duration,omitempty"`

	// Start and Max bound preset shapes. In rate mode they are rates
	// ("50/s"); in vus mode they are user counts.
	Start string `yaml:"start,omitempty" json:"start,omitempty"`
	Max   string `yaml:"max,omitempty" json:"max,omitempty"`

	Stages []Stage `yaml:"stages,omitempty" json:"stages,omitempty"`

	// Steps and StepDuration tune the breakpoint and steps shapes; Cycles
	// tunes the wave shape.
	Steps        int      `yaml:"steps,omitempty" json:"steps,omitempty"`
	StepDuration Duration `yaml:"stepDuration,omitempty" json:"stepDuration,omitempty"`
	Cycles       int      `yaml:"cycles,omitempty" json:"cycles,omitempty"`

	// Iterations runs a fixed number of journeys in total, shared by VUs.
	Iterations int `yaml:"iterations,omitempty" json:"iterations,omitempty"`

	// MaxVUs caps the user pool in rate mode (default: sized automatically).
	MaxVUs int `yaml:"maxVUs,omitempty" json:"maxVUs,omitempty"`
	// GracefulStop lets in-flight iterations finish after the end (default 30s).
	GracefulStop Duration `yaml:"gracefulStop,omitempty" json:"gracefulStop,omitempty"`
	// Abort stops the run early when the target is clearly failing.
	Abort *Abort `yaml:"abort,omitempty" json:"abort,omitempty"`
	// Replay sends recorded traffic (mode: replay).
	Replay *Replay `yaml:"replay,omitempty" json:"replay,omitempty"`
	// Regions splits a distributed run's load by worker region, such as
	// {mumbai: 50%, frankfurt: 30%, virginia: 20%}. The shares must add
	// up to 100%. In-process runs ignore it.
	Regions map[string]Percent `yaml:"regions,omitempty" json:"regions,omitempty"`
}

Load describes how much traffic to generate and its shape over time.

func (Load) Plan

func (l Load) Plan() (*Plan, error)

Plan resolves the load section into executor settings.

func (*Load) RegionFractions

func (l *Load) RegionFractions() map[string]float64

RegionFractions returns the region split as fractions, or nil when the load is not split by region.

type Loop

type Loop struct {
	Count int
	Cond  string
	Max   int
	Steps []Step
}

Loop repeats steps.

type Metadata

type Metadata struct {
	Name        string   `yaml:"name" json:"name"`
	Description string   `yaml:"description,omitempty" json:"description,omitempty"`
	Tags        []string `yaml:"tags,omitempty" json:"tags,omitempty"`
}

Metadata names and labels a scenario.

type MetricKind

type MetricKind int

MetricKind says how a metric's value is expressed.

const (
	KindLatency MetricKind = iota
	KindRatio
	KindRate
	KindCount
)

Metric kinds.

func KindOf

func KindOf(metric string) MetricKind

KindOf returns the unit family of a metric.

type Network

type Network struct {
	Profile string   `yaml:"profile,omitempty" json:"profile,omitempty"`
	RTT     Duration `yaml:"rtt,omitempty" json:"rtt,omitempty"`
	Down    string   `yaml:"down,omitempty" json:"down,omitempty"`
	Up      string   `yaml:"up,omitempty" json:"up,omitempty"`
	// Jitter varies each round trip by up to this much either way.
	Jitter Duration `yaml:"jitter,omitempty" json:"jitter,omitempty"`
	// Loss is the share of transfers stalled by a retransmission ("1%").
	Loss *Percent `yaml:"loss,omitempty" json:"loss,omitempty"`
}

Network emulates a slower network inside the load generator: a profile (slow-3g, 3g, 4g, slow-wifi) and/or explicit round-trip time and bandwidth in bits per second ("1.6mbps", "768kbps"). Explicit values override the profile's.

func (*Network) Resolve

func (n *Network) Resolve() (netem.Profile, error)

Resolve turns the network settings into a profile.

type Observe

type Observe struct {
	Prometheus *PrometheusObserve `yaml:"prometheus,omitempty" json:"prometheus,omitempty"`
	Traces     *TracesObserve     `yaml:"traces,omitempty" json:"traces,omitempty"`
}

Observe connects a run to the system under test's own telemetry.

type Overrides

type Overrides struct {
	Shape      string
	Mode       string
	VUs        int
	MaxVUs     int
	Rate       string
	Duration   string
	Start      string
	Max        string
	Iterations int
}

Overrides change a scenario's load at run time without editing the file, for example "same journeys, spike shape".

func (Overrides) Apply

func (o Overrides) Apply(s *Scenario) error

Apply rewrites the load section. A shape replaces explicit stages; a duration or rate without a shape switches to a constant executor.

type Percent

type Percent float64

Percent is a ratio stored as a fraction (1% = 0.01). It reads "1%", "0.5%" or a bare fraction such as 0.01.

func ParsePercent

func ParsePercent(s string) (Percent, error)

ParsePercent parses "1%" or a fraction.

func (Percent) MarshalJSON

func (p Percent) MarshalJSON() ([]byte, error)

func (Percent) MarshalYAML

func (p Percent) MarshalYAML() (any, error)

func (Percent) String

func (p Percent) String() string

func (*Percent) UnmarshalJSON

func (p *Percent) UnmarshalJSON(b []byte) error

func (*Percent) UnmarshalYAML

func (p *Percent) UnmarshalYAML(n *yaml.Node) error

type Persisted

type Persisted struct {
	SHA256 string `yaml:"sha256,omitempty" json:"sha256,omitempty"`
}

Persisted configures an automatic persisted query. An empty SHA256 is computed from the query.

type Plan

type Plan struct {
	Shape    string
	Mode     string
	Executor string
	// Start is the value at time zero; each stage ramps linearly from the
	// previous value to its Target. Values are users or rates per second.
	Start  float64
	Stages []PlanStage
	// Constant executors use Value for Duration.
	Value      float64
	Duration   time.Duration
	Iterations int
	VUs        int
	// Rates is the planned rate in each second of a replay plan.
	Rates []float64
	// MaxVUs caps the pool in rate mode.
	MaxVUs       int
	GracefulStop time.Duration
	// StopOnFail ends the run once a threshold fails (breakpoint shape).
	StopOnFail bool
}

Plan is a load section resolved into concrete executor settings.

func (*Plan) Peak

func (p *Plan) Peak() float64

Peak is the highest planned value (users or rate).

func (*Plan) TotalDuration

func (p *Plan) TotalDuration() time.Duration

TotalDuration is the planned length of the load phase, excluding the graceful stop.

func (*Plan) ValueAt

func (p *Plan) ValueAt(t time.Duration) float64

ValueAt returns the planned users or rate at elapsed time t.

type PlanStage

type PlanStage struct {
	Duration time.Duration
	Target   float64
}

PlanStage ramps linearly to Target over Duration.

type PluginStep

type PluginStep struct {
	// Use is "<plugin>.<step>".
	Use string
	// With is the step's config: a mapping whose strings may contain ${}
	// expressions, checked against the schema the plugin describes.
	With map[string]any
	// Check and Extract work on the JSON object the step returns.
	Check   *Check
	Extract map[string]string
	Timeout Duration
}

PluginStep runs a step implemented by a plugin, such as mqtt.publish.

type Program

type Program struct {
	Scenario   *Scenario
	BaseURL    *Template
	Headers    []KV
	Journeys   []*CJourney
	Thresholds []Threshold
	// Steps indexes every request step by ID for metric reporting.
	Steps []*CStep
	// TotalWeight is the sum of journey weights.
	TotalWeight int
}

Program is a scenario compiled for execution: every template and expression is parsed once, ahead of the run.

func Compile

func Compile(s *Scenario) (*Program, error)

Compile validates the scenario's dynamic parts and returns an executable program. It checks that every variable is defined before it is used.

A replay scenario's recording is loaded first if it is not yet, so call Compile after ResolvePaths.

func (*Program) PluginNames

func (p *Program) PluginNames() []string

PluginNames returns the plugins a program uses, sorted.

type PrometheusObserve

type PrometheusObserve struct {
	// URL is the Prometheus base URL (stampede run only). It may be
	// templated, for example ${env.PROM_URL}.
	URL string `yaml:"url,omitempty" json:"url,omitempty"`
	// BearerToken is sent as Authorization: Bearer (stampede run only).
	// It may be templated, for example ${secret.PROM_TOKEN}.
	BearerToken string `yaml:"bearerToken,omitempty" json:"bearerToken,omitempty"`
	// Integration names a Prometheus integration configured on the server
	// (server runs only; the server never fetches a URL from a scenario).
	Integration string `yaml:"integration,omitempty" json:"integration,omitempty"`
	// Queries maps a short name to a PromQL expression.
	Queries map[string]string `yaml:"queries" json:"queries"`
}

PrometheusObserve names PromQL queries charted in the report. After the run each query is evaluated over the run's time range.

func (*PrometheusObserve) QueryNames

func (p *PrometheusObserve) QueryNames() []string

QueryNames returns the query names in a stable (sorted) order.

type Rate

type Rate float64

Rate is a number of events per second. It reads "50/s", "3000/m", "100/h" or a bare number (per second).

func ParseRate

func ParseRate(s string) (Rate, error)

ParseRate parses a Stampede rate string.

func (Rate) MarshalJSON

func (r Rate) MarshalJSON() ([]byte, error)

func (Rate) MarshalYAML

func (r Rate) MarshalYAML() (any, error)

func (Rate) PerSecond

func (r Rate) PerSecond() float64

PerSecond returns the rate in events per second.

func (Rate) String

func (r Rate) String() string

func (*Rate) UnmarshalJSON

func (r *Rate) UnmarshalJSON(b []byte) error

func (*Rate) UnmarshalYAML

func (r *Rate) UnmarshalYAML(n *yaml.Node) error

type Recording

type Recording struct {
	// Endpoints are the distinct method and path templates, in order of
	// first appearance. Each becomes a journey.
	Endpoints []Endpoint
	// Arrivals are the requests to send, ordered by At.
	Arrivals []Arrival
	// Skipped counts lines or entries left out (unparseable, static,
	// other hosts, over the limit).
	Skipped int
}

Recording is a loaded replay file.

func ParseRecording

func ParseRecording(b []byte, opt Replay) (*Recording, error)

ParseRecording reads an access log or HAR file into a recording.

func (*Recording) Duration

func (r *Recording) Duration() time.Duration

Duration is when the last request is sent.

func (*Recording) RatePerSecond

func (r *Recording) RatePerSecond() []float64

RatePerSecond counts arrivals in each second.

type Replay

type Replay struct {
	// File is an access log (common/combined format) or a HAR recording.
	File string `yaml:"file" json:"file"`
	// Format is auto (default), log or har.
	Format string `yaml:"format,omitempty" json:"format,omitempty"`
	// Speed divides recorded gaps: 2 replays an hour in 30 minutes.
	Speed float64 `yaml:"speed,omitempty" json:"speed,omitempty"`
	// Limit caps the number of requests replayed (default 100000).
	Limit int `yaml:"limit,omitempty" json:"limit,omitempty"`
	// Host keeps only HAR requests to this host (default: the most
	// frequent host in the recording).
	Host string `yaml:"host,omitempty" json:"host,omitempty"`
	// Static keeps requests for static assets (.js, .css, images, fonts),
	// which are skipped by default.
	Static bool `yaml:"static,omitempty" json:"static,omitempty"`
	// contains filtered or unexported fields
}

Replay reproduces recorded traffic: every request in an access log or HAR file is sent at its recorded time (divided by Speed), as an open model, so the target sees the recorded arrival pattern.

func (*Replay) Recording

func (r *Replay) Recording() *Recording

Recording returns the loaded recording, or nil before LoadReplay.

type Request

type Request struct {
	Method  string
	URL     string
	Headers map[string]string
	Query   map[string]string
	// Exactly one body form may be set.
	JSON any
	Body string
	Form map[string]string

	Check   *Check
	Extract map[string]string
	Timeout Duration
}

Request is an HTTP call.

type SQLFeeder

type SQLFeeder struct {
	// Driver is postgres or mysql.
	Driver string `yaml:"driver" json:"driver"`
	// DSN is the connection string; ${env.X} and ${secret.X} are expanded.
	DSN   string `yaml:"dsn" json:"dsn"`
	Query string `yaml:"query" json:"query"`
	// Limit caps the rows read (default and maximum 1,000,000).
	Limit int `yaml:"limit,omitempty" json:"limit,omitempty"`
}

SQLFeeder reads a feeder's rows from a query. Each worker runs it, so the database must be reachable from the workers.

type SSE

type SSE struct {
	Request
	Until SSEUntil
}

SSE reads a server-sent event stream. Request holds the HTTP parts; the method defaults to GET, or POST when a body is set (as LLM APIs expect).

type SSEUntil

type SSEUntil struct {
	Events   int      `yaml:"events,omitempty" json:"events,omitempty"`
	Match    string   `yaml:"match,omitempty" json:"match,omitempty"`
	Duration Duration `yaml:"duration,omitempty" json:"duration,omitempty"`
}

SSEUntil says when to stop reading a stream. Events and Match are requirements: the stream must deliver them. Duration caps the stream; on its own, reaching it ends the step successfully. With none set the step reads until the server closes the stream.

type Scenario

type Scenario struct {
	APIVersion string            `yaml:"apiVersion" json:"apiVersion"`
	Kind       string            `yaml:"kind" json:"kind"`
	Metadata   Metadata          `yaml:"metadata" json:"metadata"`
	Target     Target            `yaml:"target" json:"target"`
	Vars       map[string]any    `yaml:"vars,omitempty" json:"vars,omitempty"`
	Data       map[string]Feeder `yaml:"data,omitempty" json:"data,omitempty"`
	Journeys   []Journey         `yaml:"journeys" json:"journeys"`
	Load       Load              `yaml:"load" json:"load"`
	Targets    []string          `yaml:"targets,omitempty" json:"targets,omitempty"`
	// Observe links the run to the target's own telemetry: Prometheus
	// metrics queried after the run and trace links for slow requests.
	Observe *Observe `yaml:"observe,omitempty" json:"observe,omitempty"`
	// Faults break dependencies on purpose during the run, through a
	// stampede agent running next to them.
	Faults *Faults `yaml:"faults,omitempty" json:"faults,omitempty"`
}

Scenario is a complete load test definition: what to hit, how users behave, how much load to apply and what counts as passing.

func Decode

func Decode(src []byte) (*Scenario, error)

Decode reads a scenario without semantic validation, rejecting unknown fields. Defaults are applied.

func LoadFile

func LoadFile(path string) (*Scenario, error)

LoadFile reads a scenario file. Relative feeder paths are resolved against the file's directory.

func Parse

func Parse(src []byte) (*Scenario, error)

Parse decodes and validates a scenario from YAML or JSON.

func (*Scenario) EachStep

func (s *Scenario) EachStep(fn func(Step))

EachStep calls fn for every step of every journey, nested ones included.

func (*Scenario) LoadReplay

func (s *Scenario) LoadReplay() error

LoadReplay reads the replay recording and turns each endpoint into a one-step journey. Call it after ResolvePaths; it does nothing unless load.mode is replay, and nothing the second time.

func (*Scenario) Marshal

func (s *Scenario) Marshal() ([]byte, error)

Marshal renders the scenario as YAML.

func (*Scenario) ResolvePaths

func (s *Scenario) ResolvePaths(dir string)

ResolvePaths makes relative feeder and gRPC descriptor file paths relative to dir.

func (*Scenario) Validate

func (s *Scenario) Validate() error

Validate checks the scenario's structure, then compiles every template and expression so problems surface before a run starts.

type Scope

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

Scope lists the variable names visible to an expression, beyond the built-in roots.

func NewResponseScope

func NewResponseScope(vars ...string) (*Scope, error)

NewResponseScope is a scope that also sees response variables, used by check expressions.

func NewScope

func NewScope(vars ...string) (*Scope, error)

NewScope declares vars as top-level dynamic variables.

func (*Scope) CompileExpr

func (s *Scope) CompileExpr(src string) (*Expr, error)

CompileExpr compiles a bare expression (no ${}).

func (*Scope) CompileTemplate

func (s *Scope) CompileTemplate(src string) (*Template, error)

CompileTemplate parses and compiles every ${...} in src. "$${" escapes a literal "${".

func (*Scope) Names

func (s *Scope) Names() []string

Names returns the declared variable names, sorted.

type SelectorValue

type SelectorValue struct {
	Selector string
	Value    string
}

SelectorValue is one selector and its value.

type Send

type Send struct {
	Text string
	JSON any
}

Send writes one text message: Text is a template, JSON a JSON template sent as text.

type Stage

type Stage struct {
	Duration Duration `yaml:"duration" json:"duration"`
	Target   string   `yaml:"target" json:"target"`
}

Stage linearly ramps to Target over Duration. Target is a user count in vus mode or a rate ("200/s") in rate mode.

type StatusMatcher

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

StatusMatcher matches HTTP status codes.

func ParseStatus

func ParseStatus(s string) (StatusMatcher, error)

ParseStatus parses "200", "2xx" or "200,201".

func (StatusMatcher) Empty

func (m StatusMatcher) Empty() bool

Empty reports whether no status constraint was given.

func (StatusMatcher) MarshalJSON

func (m StatusMatcher) MarshalJSON() ([]byte, error)

func (StatusMatcher) MarshalYAML

func (m StatusMatcher) MarshalYAML() (any, error)

func (StatusMatcher) Match

func (m StatusMatcher) Match(code int) bool

Match reports whether code satisfies the matcher.

func (StatusMatcher) String

func (m StatusMatcher) String() string

func (*StatusMatcher) UnmarshalJSON

func (m *StatusMatcher) UnmarshalJSON(b []byte) error

func (*StatusMatcher) UnmarshalYAML

func (m *StatusMatcher) UnmarshalYAML(n *yaml.Node) error

type Step

type Step struct {
	Kind StepKind
	// Name labels the step in reports. Requests default to "METHOD path".
	Name string
	// If skips the step unless the expression is true.
	If string

	Request *Request
	Think   *ThinkTime
	Branch  []Branch
	// Loop runs Steps Count times; While runs them while Cond holds, at
	// most Max times.
	Loop  *Loop
	Group *Group
	// Script is JavaScript run between requests; Sets names the variables
	// it sets for later steps.
	Script  string
	Sets    []string
	GraphQL *GraphQL
	SSE     *SSE
	WS      *WebSocket
	Browser *Browser
	// Action is set for goto, click, fill, press, waitFor and assert.
	Action *BrowserAction
	Send   *Send
	Expect *Expect
	GRPC   *GRPC
	Plugin *PluginStep
}

Step is one action within a journey. Exactly one kind-specific field is set; Kind records which.

func (Step) Checks

func (st Step) Checks() []*Check

Checks returns the response checks this step carries (HTTP, GraphQL, SSE and plugin steps), for code that adjusts them in place.

func (Step) MarshalJSON

func (s Step) MarshalJSON() ([]byte, error)

func (Step) MarshalYAML

func (s Step) MarshalYAML() (any, error)

func (*Step) UnmarshalJSON

func (s *Step) UnmarshalJSON(b []byte) error

UnmarshalJSON accepts the same compact form as YAML.

func (*Step) UnmarshalYAML

func (s *Step) UnmarshalYAML(n *yaml.Node) error

UnmarshalYAML reads the compact step syntax, for example

  • get: /api/products check: { status: 200 }
  • think: 2s..6s

type StepKind

type StepKind string

StepKind identifies what a step does.

const (
	StepRequest StepKind = "request"
	StepThink   StepKind = "think"
	StepBranch  StepKind = "branch"
	StepLoop    StepKind = "loop"
	StepWhile   StepKind = "while"
	StepGroup   StepKind = "group"
	StepScript  StepKind = "script"
	StepGraphQL StepKind = "graphql"
	StepSSE     StepKind = "sse"
	StepWS      StepKind = "ws"
	StepSend    StepKind = "send"
	StepExpect  StepKind = "expect"
	StepGRPC    StepKind = "grpc"
	StepPlugin  StepKind = "plugin"
	// Browser opens a real browser page; the actions after it run in
	// that page.
	StepBrowser StepKind = "browser"
	StepGoto    StepKind = "goto"
	StepClick   StepKind = "click"
	StepFill    StepKind = "fill"
	StepPress   StepKind = "press"
	StepWaitFor StepKind = "waitFor"
	StepAssert  StepKind = "assert"
)

Step kinds.

type Target

type Target struct {
	// BaseURL is prefixed to relative request paths. It may be templated,
	// for example ${env.TARGET_URL}.
	BaseURL string `yaml:"baseURL" json:"baseURL"`
	// Verify names the ownership check used for public targets:
	// "dns-txt" or "well-known". Private and loopback hosts need none.
	Verify  string            `yaml:"verify,omitempty" json:"verify,omitempty"`
	Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
	// Timeout is the default per-request timeout (default 30s).
	Timeout Duration    `yaml:"timeout,omitempty" json:"timeout,omitempty"`
	HTTP    HTTPOptions `yaml:"http,omitempty" json:"http,omitempty"`
	// Network emulates a slower network for every virtual user.
	Network *Network `yaml:"network,omitempty" json:"network,omitempty"`
}

Target describes the system under test and how to connect to it.

type Template

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

Template is a string with embedded ${expressions}.

func (*Template) IsLiteral

func (t *Template) IsLiteral() bool

IsLiteral reports whether the template has no expressions.

func (*Template) Render

func (t *Template) Render(vars interpreter.Activation) (string, error)

Render evaluates the template to a string.

func (*Template) String

func (t *Template) String() string

String returns the template source.

func (*Template) Value

func (t *Template) Value(vars interpreter.Activation) (any, error)

Value evaluates the template keeping the type when the whole template is a single expression (so "${count}" stays a number in a JSON body).

type ThinkTime

type ThinkTime struct {
	Min Duration
	Max Duration
}

ThinkTime is a pause, either fixed ("2s") or uniformly random within a range ("2s..6s").

func ParseThinkTime

func ParseThinkTime(s string) (ThinkTime, error)

ParseThinkTime parses "2s" or "2s..6s".

func (ThinkTime) MarshalJSON

func (t ThinkTime) MarshalJSON() ([]byte, error)

func (ThinkTime) MarshalYAML

func (t ThinkTime) MarshalYAML() (any, error)

func (ThinkTime) String

func (t ThinkTime) String() string

func (*ThinkTime) UnmarshalJSON

func (t *ThinkTime) UnmarshalJSON(b []byte) error

func (*ThinkTime) UnmarshalYAML

func (t *ThinkTime) UnmarshalYAML(n *yaml.Node) error

type Threshold

type Threshold struct {
	Source string
	// Scope is ScopeAll, a journey name, or "journey/step".
	Scope  string
	Metric string
	Op     string
	// Value is seconds for latency, a fraction for ratios, per second for
	// rates and a plain number for counts.
	Value float64
}

Threshold is a parsed target such as "checkout.p95 < 800ms".

func JourneyThresholds

func JourneyThresholds(j Journey) []Threshold

JourneyThresholds turns a journey's target block into thresholds.

func ParseThreshold

func ParseThreshold(src string) (Threshold, error)

ParseThreshold parses "[scope.]metric op value".

func (Threshold) FormatValue

func (t Threshold) FormatValue(v float64) string

FormatValue renders a value in the metric's unit.

func (Threshold) Pass

func (t Threshold) Pass(observed float64) bool

Pass reports whether observed satisfies the threshold.

type TracesObserve

type TracesObserve struct {
	// URL is a link template containing {traceId}, for example
	// https://jaeger.example.com/trace/{traceId}.
	URL string `yaml:"url,omitempty" json:"url,omitempty"`
	// Integration names a traces integration configured on the server.
	Integration string `yaml:"integration,omitempty" json:"integration,omitempty"`
}

TracesObserve turns the trace IDs of the slowest requests into links.

type ValidationError

type ValidationError struct {
	Problems []string
}

ValidationError lists every problem found in a scenario.

func (*ValidationError) Error

func (e *ValidationError) Error() string

type Viewport

type Viewport struct {
	Width  int `yaml:"width" json:"width"`
	Height int `yaml:"height" json:"height"`
}

Viewport is the page size in CSS pixels (default 1280×800).

type WebSocket

type WebSocket struct {
	URL          string
	Headers      map[string]string
	Subprotocols []string
	// Timeout bounds the opening handshake.
	Timeout Duration
	Steps   []Step
}

WebSocket opens a connection, runs Steps with it and closes it when they finish (or the iteration fails). URL may be ws://, wss://, http(s):// or a path joined to the base URL. Inside Steps, send and expect steps use the connection; any other step kind may be mixed in.

Jump to

Keyboard shortcuts

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