scenario

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const FormatVersion = "2"

Variables

View Source
var (
	TopKeys  = []string{"name", "target", "requires", "variables", "auth", "tls", "messaging", "data", "load", "scenario", "slo"}
	StepKeys = []string{"name", "weight", "capture", "expect"}
)

Listed here because the published schema is tested against them: a key that exists on only one side becomes autocomplete the parser refuses.

View Source
var KnownRequirements = []string{"kafka", "amqp", "mqtt", "credential"}

KnownRequirements is the closed list on purpose: an unknown name would be declared, printed and never checked by anyone, which is worse than not declaring it.

Functions

func CheckReferences

func CheckReferences(spec *Spec) error

CheckReferences applies the undeclared-variable rule to the built scenario instead of to the YAML text, which is what makes it reach the scenario written in Go. The rule and the message are the same ones the YAML path uses; what the YAML path adds is the line and the column (ADR 0002).

Without this a Go scenario accepted a ${name} that resolves from nowhere, while the same scenario in YAML was refused — one rule with two answers depending on which public wrote it.

func ClosedModelWarning

func ClosedModelWarning(spec Spec) (string, bool)

The rate is shown at three response times because that is the whole point: in the closed model it is the target that decides the load, so a single number would be the very promise this model cannot keep.

func DeclaredShare

func DeclaredShare(spec Spec, index int) float64

DeclaredShare e a proporcao que o arquivo pediu para aquele passo. Sem mix, todo passo roda em toda iteracao e a proporcao e 1.

func DescribeMessaging

func DescribeMessaging(settings *messaging.Settings) []string

DescribeMessaging is what the report is allowed to print about the broker.

func EnvironmentVariable

func EnvironmentVariable(text string) (string, bool)

EnvironmentVariable answers whether the text is only a reference, and gives the name back. The DSL asks the same question the YAML parser asks, so both audiences refuse a literal secret by the same rule.

func ExpandFromEnv

func ExpandFromEnv(text string) string

func FixedStepWarnings

func FixedStepWarnings(spec Spec) []string

A7 of the audit: a literal path never goes through interpolation, so it never enters the observed-variety check. The run hits the same URL thousands of times, the target answers from cache, and nothing in the report says so — exactly the blind spot ADR 0007 closes for data that does vary.

func GateWarnings

func GateWarnings(spec Spec) []string

GateWarnings reports what a declared gate leaves out. A scenario with several steps and only step rules approves each piece and says nothing about the wait the user actually feels, which is the sum of them.

func Interpolate

func Interpolate(text string, vars map[string]string) string

func IsEnvironmentName added in v0.6.0

func IsEnvironmentName(name string) bool

IsEnvironmentName responde se o nome segue a convencao de variavel de ambiente — MAIUSCULA — que decide o que vem de ${…} do ambiente e nao do arquivo. Um lugar so, para a interface recusar o mesmo que a expansao ignora.

func MixOrder

func MixOrder(spec Spec) []int

MixOrder devolve, para cada posicao de um ciclo, o indice do passo que roda ali. O ciclo se repete: a iteracao N executa a alternativa da posicao N % len(ordem). Devolve nil quando nao ha mix.

A ordem intercala em vez de agrupar. Sessenta chamadas de uma operacao seguidas de trinta de outra teriam a proporcao certa no fim e uma carga que nenhum sistema recebe: durante os primeiros sessenta segundos a operacao cara nao existe, e o alvo aquece um caminho so.

func ReadSeed

func ReadSeed(declared string) (int64, string, error)

ReadSeed le "semente: 42" e "semente: ${SEMENTE:-42}", devolvendo o valor que vai rodar e a variavel de ambiente de onde ele veio.

Semente fixa no arquivo faz o CI rodar sempre o mesmo caso, e um caso que passa mil vezes nao prova mais nada depois da primeira. Deixar a semente vir do ambiente e o que permite variar; guardar de onde ela veio e o que permite voltar ao caso que falhou — sem isso, variar e so perder a execucao.

func ReferencedFields

func ReferencedFields(spec Spec) map[string][]string

ReferencedFields lists, per data source, the fields the scenario reads from it. A CSV declares its columns in the file, so the check that the column exists can only happen once the file is open — and until it did, a column that was not there interpolated to nothing and the request went out with a blank in the middle of the path.

func RenamedStepKey added in v0.6.0

func RenamedStepKey(key string) (string, bool)

func RenamedTopKey added in v0.6.0

func RenamedTopKey(key string) (string, bool)

Asked before printing "unknown key": the old format is not a typo, and the suggestion by proximity would send the reader to fix eleven keys by hand.

func SeedsFromEnvironment

func SeedsFromEnvironment(spec Spec) map[string]string

SeedsFromEnvironment mapeia fonte para a variavel de ambiente que decidiu a semente dela. Fonte com semente escrita no arquivo fica de fora: nao ha o que exportar para repetir.

func UnresolvedEnvironment

func UnresolvedEnvironment(text string) []string

UnresolvedEnvironment lista as variaveis de ambiente que o texto ainda referencia e o ambiente nao tem.

Types

type ArrivalModel

type ArrivalModel string
const (
	OpenArrival   ArrivalModel = "open"
	ClosedArrival ArrivalModel = "closed"
)

type Assertion

type Assertion struct {
	Kind        AssertionKind
	Target      string
	Operator    Operator
	Value       string
	Description string
	Line        int
}

func ParseComparison

func ParseComparison(target, raw string) Assertion

type AssertionKind

type AssertionKind string
const (
	AssertStatus       AssertionKind = "status"
	AssertBodyContains AssertionKind = "bodyContains"
	AssertJSON         AssertionKind = "json"
	AssertRegex        AssertionKind = "regex"
	AssertHeader       AssertionKind = "header"
)

type Auth

type Auth struct {
	Kind         AuthKind
	Obtain       *Step
	RefreshAfter time.Duration
	Header       string
	User         string
	Password     string
	Line         int
}

type AuthKind

type AuthKind string
const (
	AuthToken  AuthKind = "token"
	AuthBasic  AuthKind = "basic"
	AuthHeader AuthKind = "header"
)

type Capture

type Capture struct {
	Variable   string
	Origin     CaptureOrigin
	Expression string
	Required   bool
	Default    string
	Line       int
}

func ParseCapture

func ParseCapture(name, text string) (Capture, error)

ParseCapture is node-free because the Go DSL comes through here too: two readings of the same expression would mean a capture that works for one audience and fails for the other.

type CaptureOrigin

type CaptureOrigin string
const (
	CaptureJSON   CaptureOrigin = "json"
	CaptureHeader CaptureOrigin = "header"
	CaptureCookie CaptureOrigin = "cookie"
	CaptureRegex  CaptureOrigin = "regex"
	CaptureBody   CaptureOrigin = "body"
	CaptureStatus CaptureOrigin = "status"
)

type Change added in v0.6.0

type Change struct {
	Line int
	From string
	To   string
}

func Migrate added in v0.6.0

func Migrate(content []byte) ([]byte, []Change, error)

Migrate rewrites by position: the document is parsed only to learn which line and column holds which key. Re-encoding the tree would have been shorter and would have thrown away every comment the author wrote.

func (Change) String added in v0.6.0

func (change Change) String() string

type Check

type Check struct {
	Kind   CheckKind
	Status int
	Text   string
}

type CheckKind

type CheckKind string
const (
	CheckStatus CheckKind = "status"
	CheckBody   CheckKind = "bodyContains"
)

type ConsumePolicy

type ConsumePolicy string
const (
	ConsumeSequential    ConsumePolicy = "sequential"
	ConsumeRandom        ConsumePolicy = "random"
	ConsumeCircular      ConsumePolicy = "circular"
	ConsumeUniquePerUser ConsumePolicy = "uniquePerUser"
)

type DataSource

type DataSource struct {
	Name    string
	File    string
	Consume ConsumePolicy
	Seed    int64
	// Name of the environment variable the seed came from, empty when it was
	// written in the file. Reproducing a run means knowing which seed ran and
	// where it came from, and there is no way to know that later.
	SeedFrom string
	Fields   map[string]Generator
	Records  int
	Line     int
}

func (DataSource) Synthetic

func (dataSource DataSource) Synthetic() bool

func (DataSource) UsesSeed

func (source DataSource) UsesSeed() bool

A semente so muda o que sai de uma fonte que usa aleatoriedade: sintetica sempre, e CSV so quando o consumo e aleatorio. Publicar uma semente que nao muda nada seria ruido no bloco que a pessoa le para reproduzir.

type Generator

type Generator struct {
	Recipe string
	Format string
	PerUse bool
}

PerUse is off by default: the same generated value has to hold for the whole iteration, which is what an idempotency key needs — the same transactionId in two requests, a new one on the next iteration. Wanting a new value at every substitution is the rare case, so it is declared.

func ParseGenerator

func ParseGenerator(recipe string) Generator

type LoadPlan

type LoadPlan struct {
	Model     ArrivalModel
	Phases    []Phase
	Users     int
	For       time.Duration
	ThinkTime time.Duration
}

func (LoadPlan) Closed

func (plan LoadPlan) Closed() bool

type Operator

type Operator string
const (
	OpEqual          Operator = "=="
	OpNotEqual       Operator = "!="
	OpLess           Operator = "<"
	OpLessOrEqual    Operator = "<="
	OpGreater        Operator = ">"
	OpGreaterOrEqual Operator = ">="
	OpContains       Operator = "contains"
	OpExists         Operator = "exists"
)

type Phase

type Phase struct {
	Kind PhaseKind
	From float64
	To   float64
	For  time.Duration
	Line int
}

func (Phase) FinalRate

func (phase Phase) FinalRate() float64

func (Phase) InitialRate

func (phase Phase) InitialRate() float64

type PhaseKind

type PhaseKind string
const (
	PhaseRamp   PhaseKind = "ramp"
	PhaseSteady PhaseKind = "steady"
	PhaseSpike  PhaseKind = "spike"
)

type SLORule

type SLORule struct {
	Scope    SLOScope
	Step     string
	Metric   string
	Operator Operator
	Limit    float64
	Unit     string
	Text     string
	Line     int
}

func ParseSLORule

func ParseSLORule(target, metric, rawLimit string) (SLORule, error)

func (SLORule) Overall

func (sloRule SLORule) Overall() bool

type SLOScope

type SLOScope string
const (
	ScopeStep       SLOScope = "step"
	ScopeOverall    SLOScope = "global"
	ScopeJourney    SLOScope = "journey"
	ScopeRegression SLOScope = "regression"
)

type ScenarioError

type ScenarioError struct {
	File    string
	Line    int
	Column  int
	Message string
}

func (ScenarioError) Error

func (scenarioError ScenarioError) Error() string

type Spec

type Spec struct {
	FormatVersion string
	Name          string
	Target        string
	Requires      []string
	// Names referenced as ${NOME} that only the environment can supply and that
	// were not in it when the file was read. Not part of what the file says —
	// part of what the machine had — so the DSL does not carry it.
	MissingEnvironment []string
	Vars               map[string]string
	Auth               *Auth
	Messaging          *messaging.Settings
	// TLS of the HTTP target. Kafka and AMQP declare theirs inside 'messaging';
	// HTTP had nowhere to say it, and homologation behind a private CA could not
	// be tested at all.
	TLS   *messaging.TLS
	Data  []DataSource
	Load  LoadPlan
	Steps []Step
	SLO   []SLORule
}

func Parse

func Parse(content []byte) (Spec, error)

func ParseFile

func ParseFile(path string) (Spec, error)

func (Spec) Duration

func (spec Spec) Duration() time.Duration

func (Spec) FindStep

func (spec Spec) FindStep(name string) (Step, error)

func (Spec) HasMix

func (spec Spec) HasMix() bool

HasMix diz se o cenario declara mix. Sem mix, todo passo roda em toda iteracao, que e o comportamento que sempre existiu.

func (*Spec) ResolveWith added in v0.6.0

func (spec *Spec) ResolveWith(environment map[string]string)

ResolveWith injeta valores que nao vieram do arquivo — o ambiente, ou um valor que a interface guarda so na memoria da sessao. O arquivo mantem ${NOME} e nunca o literal, entao a recusa de credencial no arquivo fica intacta: isto e o mesmo "de onde, nao qual" que a variavel de ambiente ja e. Ver ADR 0021.

Vars vira um mapa novo para nao alterar o do chamador, e o nome deixa de contar como ausente — sem isso a execucao seria recusada por falta de uma variavel que a sessao acabou de fornecer.

Credencial de broker vai para o campo de conexao, nao para os Vars: e de la que o cliente a le. Pos-la nos Vars limparia o aviso e ainda falharia ao conectar.

func (*Spec) SessionCredentials added in v0.6.0

func (spec *Spec) SessionCredentials() []string

SessionCredentials sao as variaveis que faltam e que o campo de sessao entrega: as de HTTP pelos Vars do runtime, as de broker no campo de conexao.

func (Spec) Validate

func (c Spec) Validate() error

type Step

type Step struct {
	Name     string
	Protocol string
	Config   protocol.Config
	// Weight of the alternative in the mix. Zero when the scenario declares no
	// mix, and then every step runs on every iteration. See ADR 0016.
	Weight     int
	Checks     []Check
	Captures   []Capture
	Assertions []Assertion
	Line       int
}

func (Step) AggregationKey

func (step Step) AggregationKey() string

Jump to

Keyboard shortcuts

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