bench

package module
v0.0.0-...-9595877 Latest Latest
Warning

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

Go to latest
Published: Jan 9, 2024 License: MIT Imports: 36 Imported by: 0

README

ベンチマーカー

localでの実行方法
go run cmd/bench/main.go -target-url https://t.isucon.dev

各種オプションは以下を参照してください。

Usage of bench:
  -data-dir string
        Data directory (default "data")
  -debug
        Debug mode
  -duration duration
        Benchmark duration (default 1m0s)
  -exit-error-on-fail
        Exit error on fail
  -initialize-request-timeout duration
        Initialize request timeout (default 30s)
  -prepare-only
        Prepare only
  -reproduce
        reproduce contest day mode. default: false
  -request-timeout duration
        Default request timeout (default 30s)
  -skip-prepare
        Skip prepare
  -strict-prepare
        strict prepare mode. default: true (default true)
  -target-addr string
        Benchmark target address e.g. host:port
  -target-url string
        Benchmark target URL (default "https://t.isucon.dev")

webappはhost名を見てテナントDBを振り分けるため、--target-urlにはテナント名のsubdomainを加える前のURLを指定します。
--target-addrには実際にリクエストするwebappのアドレスを指定します。

例: 10.0.0.1:443に向けてベンチマークを実行する場合

go run cmd/bench/main.go -target-url https://t.isucon.dev --target-addr 10.0.0.1:443
想定負荷の流れ
  • SaaS管理者 (1 worker)

    • /api/admin/tenants/billingを最新から順番に取得する
    • すべて見終わったらテナントを1つ作成し、NewTenantScenarioを開始する
  • Organizer

    • 以下を繰り返す
      • 大会を追加
        • playerを追加
        • 大会を開催する
          • 以下を並列で実行する
          • CSV入稿
          • 複数のplayerがrankingを取得する
        • 大会のfinish
        • rankingの確認
      • /api/organizer/billingを取得する
  • Player

    • workerとして、離脱条件を満たさない限り以下を繰り返す
      • テナント内の大会の一覧を取得する
      • 大会のうちの一つのrankingを参照する
        • 1秒(厳密には1.2秒)レスポンスが帰ってこなければ離脱としてworkerを終了する
      • rankingの中からplayerを選び、/api/player/player/:player_nameを参照する

シナリオ一覧

  • AdminBillingScenario : SaaS管理者
  • PlayerScenario : 参加者
  • OrganizerNewTenantScenario : 新規テナント
  • PopularTenantScenario : 既存テナント
  • AdminBillingValidateScenario : 管理者請求額整合性チェック
  • TenantBillingValidateScenario : テナント請求額整合性チェック
  • PlayerValidateScenario : プレイヤー整合性チェック
  • ValidateScenario : 整合性チェック
構成

Scenario_xxx

  • workerとして動作するもの job_xxx
  • Action+Validationのまとまり
  • 終わるまでブロックする
  • Scenarioの中で利用する
Reproduce mode(コンテスト当日の再現について)

負荷走行の一部で本来意図していない挙動をしていた点について、競技終了後に修正を行いました。

修正点

  • GET /api/player/competition/:competition_id/rankingが空の内容を返した際に、再度リクエストする前にsleepが入るようになりました。

修正により、コンテスト当日と比べてベンチマークスコアが低くなることがあります。
コンテスト当日のベンチマーカーの挙動を再現する場合は-reproduceをつけてベンチマーカーを実行してください。
デフォルトは無効になっています。

Documentation

Index

Constants

View Source
const (
	ConstMaxError         = 30
	ConstMaxCriticalError = 10

	// PlayerScenario
	ConstPlayerScenarioCompetitionLoopCount = 10 // 一周でいくつ大会を見るか
	ConstPlayerScenarioMaxPlayerCount       = 10 // 大会1つあたり何人のプレイヤー詳細を見るか(最大値)

	// TenantBillingValidateScenario
	ConstTenantBillingValidateScenarioPlayerNum = 100 // TenantBilling検証用テナントのplayer数

	// AdminBillingValidateScenario
	ConstAdminBillingValidateScenarioPlayerNum = 100 // TenantBilling検証用テナントのplayer数
)
View Source
const (
	AccountRoleAdmin     = "admin"
	AccountRoleOrganizer = "organizer"
	AccountRolePlayer    = "player"
)
View Source
const (
	ErrFailedPrepare failure.StringCode = "fail-prepare"
	ErrFailedLoad    failure.StringCode = "fail-load"

	ErrNormalError   failure.StringCode = "error-normal"
	ErrCriticalError failure.StringCode = "error-critical"
)
View Source
const (
	ScorePOSTAdminTenantsAdd             score.ScoreTag = "POST /api/admin/tenants/add"
	ScoreGETAdminTenantsBilling          score.ScoreTag = "GET /api/admin/tenants/billing"
	ScoreGETOrganizerPlayersList         score.ScoreTag = "GET /api/organizer/players/list"
	ScorePOSTOrganizerPlayersAdd         score.ScoreTag = "POST /api/organizer/players/add"
	ScorePOSTOrganizerPlayerDisqualified score.ScoreTag = "POST /api/organizer/player/:player_name/disqualified"
	ScorePOSTOrganizerCompetitionsAdd    score.ScoreTag = "POST /api/organizer/competitions/add"
	ScorePOSTOrganizerCompetitionFinish  score.ScoreTag = "POST /api/organizer/competition/:competition_id/finish"
	ScorePOSTOrganizerCompetitionScore   score.ScoreTag = "POST /api/organizer/competition/:competition_id/score"
	ScoreGETOrganizerBilling             score.ScoreTag = "GET /api/organizer/billing"
	ScoreGETOrganizerCompetitions        score.ScoreTag = "GET /api/organizer/competitions"
	ScoreGETPlayerDetails                score.ScoreTag = "GET /api/player/player/:player_name"
	ScoreGETPlayerRanking                score.ScoreTag = "GET /api/player/competition/:competition_id/ranking"
	ScoreGETPlayerCompetitions           score.ScoreTag = "GET /api/player/competitions"
)

シナリオで発生するスコアのタグ

View Source
const (
	ErrValidation failure.StringCode = "load-validation"
)

failure.NewError で用いるエラーコード定義

Variables

View Source
var (
	// NOTE: 初期データ範囲
	// 1: ISUコングロマリット(巨大テナント)
	ConstPopularTenantScenarioIDRange        = []int{1, 29}  // 破壊的変更NGで
	ConstValidateScenarioAdminBillingIDRange = []int{12, 29} // 整合性チェックで利用
	ConstAdminBillingValidateScenarioIDRange = []int{30, 69} // 大会追加OK
	ConstPlayerValidateScenarioIDRange       = []int{70, 99} // 破壊的変更OK
)
View Source
var (
	// 選手向け情報を出力するロガー
	ContestantLogger = log.New(os.Stdout, "", log.Ltime|log.Lmicroseconds)
	// 大会運営向け情報を出力するロガー
	AdminLogger = log.New(os.Stderr, "[ADMIN] ", log.Ltime|log.Lmicroseconds)
)
View Source
var (
	Debug = false

	// これ以上エラーが出たら打ち切り
	MaxErrors = 30

	// エラーが発生したらこの時間だけSleepする(暴発防止)
	SleepOnError = time.Second
)

各tagのリスト

ScoreTag毎の倍率

Functions

func GetAdminTenantsBillingAction

func GetAdminTenantsBillingAction(ctx context.Context, beforeTenantID string, ag *agent.Agent) (*http.Response, error, string)

func GetFile

func GetFile(ctx context.Context, ag *agent.Agent, path string) (*http.Response, error)

func GetOrganizerBillingAction

func GetOrganizerBillingAction(ctx context.Context, ag *agent.Agent) (*http.Response, error, string)

func GetOrganizerCompetitionsAction

func GetOrganizerCompetitionsAction(ctx context.Context, ag *agent.Agent) (*http.Response, error, string)

func GetOrganizerPlayersListAction

func GetOrganizerPlayersListAction(ctx context.Context, ag *agent.Agent) (*http.Response, error, string)

func GetPlayerAction

func GetPlayerAction(ctx context.Context, playerID string, ag *agent.Agent) (*http.Response, error, string)

func GetPlayerCompetitionRankingAction

func GetPlayerCompetitionRankingAction(ctx context.Context, competitionID string, rankAfter string, ag *agent.Agent) (*http.Response, error, string)

func GetPlayerCompetitionsAction

func GetPlayerCompetitionsAction(ctx context.Context, ag *agent.Agent) (*http.Response, error, string)

func InitializeData

func InitializeData()

func LoadFromJSONFile

func LoadFromJSONFile[T LoadModel](jsonFile string) ([]*T, error)

func PostAdminTenantsAddAction

func PostAdminTenantsAddAction(ctx context.Context, name, displayName string, ag *agent.Agent) (*http.Response, error, string)

func PostInitializeAction

func PostInitializeAction(ctx context.Context, ag *agent.Agent) (*http.Response, error)

func PostOrganizerApiPlayerDisqualifiedAction

func PostOrganizerApiPlayerDisqualifiedAction(ctx context.Context, playerID string, ag *agent.Agent) (*http.Response, error, string)

func PostOrganizerCompetitionFinishAction

func PostOrganizerCompetitionFinishAction(ctx context.Context, competitionID string, ag *agent.Agent) (*http.Response, error, string)

func PostOrganizerCompetitionScoreAction

func PostOrganizerCompetitionScoreAction(ctx context.Context, competitionID string, csv []byte, ag *agent.Agent) (*http.Response, error, string)

func PostOrganizerCompetitionsAddAction

func PostOrganizerCompetitionsAddAction(ctx context.Context, title string, ag *agent.Agent) (*http.Response, error, string)

func PostOrganizerPlayersAddAction

func PostOrganizerPlayersAddAction(ctx context.Context, playerDisplayNames []string, ag *agent.Agent) (*http.Response, error, string)

func RequestWithRetry

func RequestWithRetry(ctx context.Context, reqFn func() (*http.Request, error), doFn func(*http.Request) (*http.Response, error)) (*http.Response, error)

429 Too Many Requestsの場合にretry after分待ってretryする

func SleepWithCtx

func SleepWithCtx(ctx context.Context, sleepTime time.Duration)

Types

type Account

type Account struct {
	Agent      *agent.Agent
	Option     Option // SetJWT時にGetAgentをしたいのでしぶしぶ含めた
	Role       string
	TenantName string // JWTのaudience adminの場合は空(あるいは無視)
	PlayerID   string // JWTのsubject

	// Invalid JWT用 セットされていなければ有効な鍵がセットされる
	InvalidRSAKey  bool
	InvalidKeyArgo bool
	// contains filtered or unexported fields
}

func (*Account) GetAgent

func (ac *Account) GetAgent() (*agent.Agent, error)

func (*Account) GetRequestURL

func (ac *Account) GetRequestURL() string

{admin,[tenantName]}.t.isucon.dev 的なURLを組み立てる

func (*Account) SetJWT

func (ac *Account) SetJWT(rawkey *rsa.PrivateKey, isValidExp bool) error

SetJWT Agentがなければ作って、JWTをcookieに入れる

func (*Account) String

func (ac *Account) String() string

type CompactLogger

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

func NewCompactLog

func NewCompactLog(lgr *log.Logger, wg sync.WaitGroup) *CompactLogger

func (*CompactLogger) Log

func (cl *CompactLogger) Log()

func (*CompactLogger) Printf

func (cl *CompactLogger) Printf(format string, args ...any)

type CompetitionData

type CompetitionData struct {
	ID    string
	Title string
}

type InitialDataRow

type InitialDataRow data.BenchmarkerSource

type InitialDataRows

type InitialDataRows []*InitialDataRow

func GetInitialData

func GetInitialData() (InitialDataRows, error)

func (InitialDataRows) Choise

func (idrs InitialDataRows) Choise() *InitialDataRow

type InitialDataTenantRow

type InitialDataTenantRow data.BenchmarkerTenantSource

type InitialDataTenantRows

type InitialDataTenantRows []*InitialDataTenantRow

func GetInitialDataTenant

func GetInitialDataTenant() (InitialDataTenantRows, error)

type LoadModel

type LoadModel interface {
	InitialDataRow | InitialDataTenantRow
}

type Option

type Option struct {
	TargetURL                string
	TargetAddr               string
	RequestTimeout           time.Duration
	InitializeRequestTimeout time.Duration
	ExitErrorOnFail          bool
	Duration                 time.Duration
	PrepareOnly              bool
	SkipPrepare              bool
	DataDir                  string
	Debug                    bool
	StrictPrepare            bool
	Reproduce                bool
}

func (Option) NewAgent

func (o Option) NewAgent(targetURL string, forInitialize bool) (*agent.Agent, error)

func (Option) NewTransport

func (o Option) NewTransport() *http.Transport

func (Option) String

func (o Option) String() string

type OrganizerJobConfig

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

type OrganizerJobResult

type OrganizerJobResult struct {
	ScoredPlayerNum int
}

type PlayerData

type PlayerData struct {
	ID          string
	DisplayName string
}

type Response

type Response struct {
	Response *http.Response // Bodyは読み取り済み
	Body     string
}

Bodyを繰り返し取れるように先に読んでStringとして置いておく

func ReadResponse

func ReadResponse(res *http.Response) *Response

type ResponseAPIBase

type ResponseAPIBase struct {
	Status  bool   `json:"status"`
	Message string `json:"message,omitempty"`
}

func (ResponseAPIBase) ErrorMessage

func (r ResponseAPIBase) ErrorMessage() string

func (ResponseAPIBase) IsSuccess

func (r ResponseAPIBase) IsSuccess() bool

type ResponseAPIBilling

type ResponseAPIBilling struct {
	ResponseAPIBase
	Data isuports.BillingHandlerResult `json:"data"`
}

type ResponseAPICompetitionRanking

type ResponseAPICompetitionRanking struct {
	ResponseAPIBase
	Data isuports.CompetitionRankingHandlerResult `json:"data"`
}

type ResponseAPICompetitionRankingFinish

type ResponseAPICompetitionRankingFinish struct {
	ResponseAPIBase
}

type ResponseAPICompetitionResult

type ResponseAPICompetitionResult struct {
	ResponseAPIBase
	Data isuports.ScoreHandlerResult `json:"data"`
}

type ResponseAPICompetitions

type ResponseAPICompetitions struct {
	ResponseAPIBase
	Data isuports.CompetitionsHandlerResult `json:"data"`
}

type ResponseAPICompetitionsAdd

type ResponseAPICompetitionsAdd struct {
	ResponseAPIBase
	Data isuports.CompetitionsAddHandlerResult `json:"data"`
}

type ResponseAPIInitialize

type ResponseAPIInitialize struct {
	ResponseAPIBase
	Data isuports.InitializeHandlerResult `json:"data"`
}

type ResponseAPIPlayer

type ResponseAPIPlayer struct {
	ResponseAPIBase
	Data isuports.PlayerHandlerResult `json:"data"`
}

type ResponseAPIPlayerDisqualified

type ResponseAPIPlayerDisqualified struct {
	ResponseAPIBase
	Data isuports.PlayerDisqualifiedHandlerResult `json:"data"`
}

type ResponseAPIPlayersAdd

type ResponseAPIPlayersAdd struct {
	ResponseAPIBase
	Data isuports.PlayersAddHandlerResult `json:"data"`
}

type ResponseAPIPlayersList

type ResponseAPIPlayersList struct {
	ResponseAPIBase
	Data isuports.PlayersListHandlerResult `json:"data"`
}

type ResponseAPITenantsAdd

type ResponseAPITenantsAdd struct {
	ResponseAPIBase
	Data isuports.TenantsAddHandlerResult `json:"data"`
}

type ResponseAPITenantsBilling

type ResponseAPITenantsBilling struct {
	ResponseAPIBase
	Data isuports.TenantsBillingHandlerResult `json:"data"`
}

type ResponseValidator

type ResponseValidator func(*Response) error

レスポンスを検証するバリデータ関数の型

func WithBodySameFile

func WithBodySameFile(filePath string) ResponseValidator

func WithCacheControlPrivate

func WithCacheControlPrivate() ResponseValidator

func WithContentType

func WithContentType(wantContentType string) ResponseValidator

func WithErrorResponse

func WithErrorResponse[T ResponseAPI]() ResponseValidator

func WithStatusCode

func WithStatusCode(statusCodes ...int) ResponseValidator

ステータスコードコードを検証するバリデータ関数を返す高階関数 例: ValidateResponse(res, WithStatusCode(200, 304))

func WithSuccessResponse

func WithSuccessResponse[T ResponseAPI](validates ...func(res T) error) ResponseValidator

type Scenario

type Scenario struct {
	Option Option
	Errors failure.Errors

	ScenarioScoreMap   sync.Map // map[string]*int64
	ScenarioCountMap   map[ScenarioTag][]int
	WorkerCountMap     map[string]int
	ScenarioCountMutex sync.Mutex
	WorkerCountMutex   sync.Mutex

	InitialData        InitialDataRows
	InitialDataTenant  InitialDataTenantRows
	DisqualifiedPlayer map[string]struct{}
	RawKey             *rsa.PrivateKey

	WorkerCh        chan Worker
	ErrorCh         chan struct{}
	CriticalErrorCh chan struct{}

	HeavyTenantCount int

	CompetitionAddLog *CompactLogger
	TenantAddLog      *CompactLogger
	PlayerAddCountMu  sync.Mutex
	PlayerAddCount    int
	PlayerDelCountMu  sync.Mutex
	PlayerDelCount    int
	// contains filtered or unexported fields
}

オプションと全データを持つシナリオ構造体

func (*Scenario) AddCriticalCount

func (sc *Scenario) AddCriticalCount()

func (*Scenario) AddErrorCount

func (sc *Scenario) AddErrorCount()

func (*Scenario) AddScoreByScenario

func (sc *Scenario) AddScoreByScenario(step *isucandar.BenchmarkStep, scoreTag score.ScoreTag, scenarioTag ScenarioTag)

どのシナリオから加算されたスコアかをカウントしならがスコアを追加する

func (*Scenario) AdminBillingScenario

func (sc *Scenario) AdminBillingScenario(ctx context.Context, step *isucandar.BenchmarkStep, scTag ScenarioTag) error

func (*Scenario) AdminBillingScenarioWorker

func (sc *Scenario) AdminBillingScenarioWorker(step *isucandar.BenchmarkStep, p int32) (Worker, error)

ずっと/admin/billingを見続けるシナリオ

func (*Scenario) AdminBillingValidate

func (sc *Scenario) AdminBillingValidate(ctx context.Context, step *isucandar.BenchmarkStep) error

func (*Scenario) AdminBillingValidateWorker

func (sc *Scenario) AdminBillingValidateWorker(step *isucandar.BenchmarkStep, p int32) (*adminBillingValidateWorker, error)

func (*Scenario) CountWorker

func (sc *Scenario) CountWorker(name string)

func (*Scenario) CountdownWorker

func (sc *Scenario) CountdownWorker(ctx context.Context, name string)

func (*Scenario) GetAccountAndAgent

func (sc *Scenario) GetAccountAndAgent(role, tenantName, playerID string) (*Account, *agent.Agent, error)

Accountを作成してAccountとagent.Agentを返す

func (*Scenario) Load

func (sc *Scenario) Load(ctx context.Context, step *isucandar.BenchmarkStep) error

ベンチ本編 isucandar.LoadScenario を満たすメソッド isucandar.Benchmark の Load ステップで実行される

func (*Scenario) NewTenantScenario

func (sc *Scenario) NewTenantScenario(ctx context.Context, step *isucandar.BenchmarkStep, tenant *isuports.TenantRow) error

func (*Scenario) NewTenantScenarioWorker

func (sc *Scenario) NewTenantScenarioWorker(step *isucandar.BenchmarkStep, tenant *isuports.TenantRow, p int32) (*newTenantScenarioWorker, error)

func (*Scenario) OrganizerJob

大会を作成, スコアを増やしながら入れる, 確定する

func (*Scenario) PlayerAddCountAdd

func (sc *Scenario) PlayerAddCountAdd(num int)

func (*Scenario) PlayerAddCountPrint

func (sc *Scenario) PlayerAddCountPrint()

func (*Scenario) PlayerDelCountAdd

func (sc *Scenario) PlayerDelCountAdd(num int)

func (*Scenario) PlayerDelCountPrint

func (sc *Scenario) PlayerDelCountPrint()

func (*Scenario) PlayerScenario

func (sc *Scenario) PlayerScenario(ctx context.Context, step *isucandar.BenchmarkStep, scTag ScenarioTag, tenantName, playerID string) error

本来意図していた挙動版

func (*Scenario) PlayerScenarioReproduce

func (sc *Scenario) PlayerScenarioReproduce(ctx context.Context, step *isucandar.BenchmarkStep, scTag ScenarioTag, tenantName, playerID string) error

以下は予選開催時の状態

func (*Scenario) PlayerScenarioWorker

func (sc *Scenario) PlayerScenarioWorker(step *isucandar.BenchmarkStep, p int32, tenantName, playerID string) (Worker, error)

competition一覧を取り、rankingを参照するプレイヤー

func (*Scenario) PlayerValidateScenario

func (sc *Scenario) PlayerValidateScenario(ctx context.Context, step *isucandar.BenchmarkStep, scTag ScenarioTag) error

func (*Scenario) PlayerValidateScenarioWorker

func (sc *Scenario) PlayerValidateScenarioWorker(step *isucandar.BenchmarkStep, p int32) (Worker, error)

PlayerHandlerが不正な値を返さないかチェックする

func (*Scenario) PopularTenantScenario

func (sc *Scenario) PopularTenantScenario(ctx context.Context, step *isucandar.BenchmarkStep, scTag ScenarioTag, isHeavyTenant bool) error

func (*Scenario) PopularTenantScenarioWorker

func (sc *Scenario) PopularTenantScenarioWorker(step *isucandar.BenchmarkStep, p int32, isHeavyTenant bool) (Worker, error)

func (*Scenario) Prepare

func (sc *Scenario) Prepare(ctx context.Context, step *isucandar.BenchmarkStep) error

isucandar.PrepeareScenario を満たすメソッド isucandar.Benchmark の Prepare ステップで実行される

func (*Scenario) PrintScenarioCount

func (sc *Scenario) PrintScenarioCount()

func (*Scenario) PrintScenarioScoreMap

func (sc *Scenario) PrintScenarioScoreMap()

シナリオ毎のスコア表示

func (*Scenario) PrintWorkerCount

func (sc *Scenario) PrintWorkerCount()

func (*Scenario) ScenarioError

func (sc *Scenario) ScenarioError(scTag ScenarioTag, err error)

func (*Scenario) ScenarioStart

func (sc *Scenario) ScenarioStart(scTag ScenarioTag)

シナリオ回転数

func (*Scenario) TenantBillingValidate

func (sc *Scenario) TenantBillingValidate(ctx context.Context, step *isucandar.BenchmarkStep) error

func (*Scenario) TenantBillingValidateWorker

func (sc *Scenario) TenantBillingValidateWorker(step *isucandar.BenchmarkStep, p int32) (*tenantBillingValidateWorker, error)

3回までリトライOK

func (*Scenario) ValidationScenario

func (sc *Scenario) ValidationScenario(ctx context.Context, step *isucandar.BenchmarkStep) error

ベンチ実行前の整合性検証シナリオ isucandar.ValidateScenarioを満たすメソッド isucandar.Benchmark の validation ステップで実行される

type ScenarioTag

type ScenarioTag string

シナリオ分別用タグ

const (
	ScenarioTagAdminBilling            ScenarioTag = "AdminBilling"
	ScenarioTagOrganizerNewTenant      ScenarioTag = "OrganizerNewTenant"
	ScenarioTagOrganizerPopularTenant  ScenarioTag = "OrganizerPopularTenant"
	ScenarioTagOrganizerPeacefulTenant ScenarioTag = "OrganizerPeacefulTenant"
	ScenarioTagPlayer                  ScenarioTag = "Player"
	ScenarioTagPlayerValidate          ScenarioTag = "PlayerValidate"
	ScenarioTagTenantBillingValidate   ScenarioTag = "TenantBillingValidate"
	ScenarioTagAdminBillingValidate    ScenarioTag = "AdminBillingValidate"
)

func (ScenarioTag) String

func (st ScenarioTag) String() string

type ScoreRow

type ScoreRow struct {
	PlayerID string
	Score    int
}

type ScoreRows

type ScoreRows []*ScoreRow

func (ScoreRows) CSV

func (srs ScoreRows) CSV() string

func (ScoreRows) PlayerIDs

func (srs ScoreRows) PlayerIDs() []string

type TenantData

type TenantData struct {
	DisplayName string
	Name        string
}

type ValidationError

type ValidationError struct {
	Errors   []error
	Title    string
	Canceled bool
}

func ValidateResponse

func ValidateResponse(title string, step *isucandar.BenchmarkStep, res *http.Response, err error, validators ...ResponseValidator) ValidationError

レスポンスを検証する関数 複数のバリデータ関数を受け取ってすべてでレスポンスを検証し、 ValidationError を返す

func ValidateResponseWithMsg

func ValidateResponseWithMsg(title string, step *isucandar.BenchmarkStep, res *http.Response, err error, msg string, validators ...ResponseValidator) ValidationError

func (ValidationError) Add

func (ValidationError) Error

func (v ValidationError) Error() string

error インターフェースを満たす Error メソッド

func (ValidationError) IsEmpty

func (v ValidationError) IsEmpty() bool

ValidationError が空かを判定 NOTE: contextのキャンセルによって返されるValidationErrorは、IsEmptyはfalseでErrorsは空

type Worker

type Worker interface {
	String() string
	Process(context.Context)
}

isucandar worker.Workerを実装する

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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