mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 17:50:12 +00:00
170 lines
5.9 KiB
Go
170 lines
5.9 KiB
Go
//go:build linux
|
|
|
|
package scenario
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/nezhahq/nezha/integration/agentcompat/internal/contract"
|
|
)
|
|
|
|
var (
|
|
ErrStressEvidence = errors.New("stress evidence is invalid")
|
|
ErrStressFault = errors.New("stress worker fault evidence is invalid")
|
|
)
|
|
|
|
type StressPreparedBinaries struct {
|
|
DashboardBuildCount int `json:"dashboard_build_count"`
|
|
DashboardPathReused bool `json:"dashboard_path_reused"`
|
|
AgentBuildCount int `json:"agent_build_count"`
|
|
AgentPathReused bool `json:"agent_path_reused"`
|
|
}
|
|
|
|
type StressQuotaBoundary struct {
|
|
Allowed int `json:"allowed"`
|
|
Rejected int `json:"rejected"`
|
|
AllowedAccepted bool `json:"allowed_accepted"`
|
|
RejectedDenied bool `json:"rejected_denied"`
|
|
}
|
|
|
|
type StressQuotaEvidence struct {
|
|
PATSecond StressQuotaBoundary `json:"pat_second"`
|
|
PATMinute StressQuotaBoundary `json:"pat_minute"`
|
|
UserStreams StressQuotaBoundary `json:"user_streams"`
|
|
ServerStreams StressQuotaBoundary `json:"server_streams"`
|
|
PathLockStripes int `json:"path_lock_stripes"`
|
|
}
|
|
|
|
type StressWarmupEvidence struct {
|
|
Agent StressAgentOrdinal `json:"agent"`
|
|
Exec bool `json:"exec"`
|
|
Filesystem bool `json:"filesystem"`
|
|
Terminal bool `json:"terminal"`
|
|
NAT bool `json:"nat"`
|
|
FM bool `json:"file_manager"`
|
|
}
|
|
|
|
type StressSessionEvidence struct {
|
|
ID StressSessionID `json:"id"`
|
|
Kind StressSessionKind `json:"kind"`
|
|
Succeeded bool `json:"succeeded"`
|
|
}
|
|
|
|
type StressFaultTarget struct {
|
|
Iteration int `json:"iteration"`
|
|
Round int `json:"round"`
|
|
Agent StressAgentOrdinal `json:"agent"`
|
|
Kind StressOperationKind `json:"kind"`
|
|
}
|
|
|
|
type StressCleanupSummary struct {
|
|
Passed bool `json:"passed"`
|
|
ReceiptCount int `json:"receipt_count"`
|
|
FailedReceiptCount int `json:"failed_receipt_count"`
|
|
ForcedCleanupCount int `json:"forced_cleanup_count"`
|
|
ProcessResidue int `json:"process_residue"`
|
|
ProcessGroupResidue int `json:"process_group_residue"`
|
|
WorkspaceResidue int `json:"workspace_residue"`
|
|
}
|
|
|
|
type StressIterationEvidence struct {
|
|
Iteration int `json:"iteration"`
|
|
Rounds []StressRoundEvidence `json:"rounds"`
|
|
Resources []StressProcessWindows `json:"resources"`
|
|
}
|
|
|
|
type StressEvidence struct {
|
|
Version int `json:"version"`
|
|
Profile contract.ProfileName `json:"profile"`
|
|
Seed contract.Seed `json:"seed"`
|
|
PreparedBinaries StressPreparedBinaries `json:"prepared_binaries"`
|
|
Quotas StressQuotaEvidence `json:"quotas"`
|
|
Warmups []StressWarmupEvidence `json:"warmups"`
|
|
Sessions []StressSessionEvidence `json:"sessions"`
|
|
Plan StressPlan `json:"plan"`
|
|
Iterations []StressIterationEvidence `json:"iterations"`
|
|
FaultTarget *StressFaultTarget `json:"fault_target,omitempty"`
|
|
SoakTrend StressSoakTrendEvidence `json:"soak_trend,omitempty"`
|
|
Cleanup StressCleanupSummary `json:"cleanup"`
|
|
}
|
|
|
|
func StressWorkerFaultTarget() StressFaultTarget {
|
|
agent, err := NewStressAgentOrdinal(4)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return StressFaultTarget{Iteration: 1, Round: 2, Agent: agent, Kind: StressOperationExec}
|
|
}
|
|
|
|
func (e StressEvidence) ValidateSuccess(profile contract.Profile) error {
|
|
return e.validate(profile, false)
|
|
}
|
|
|
|
func (e StressEvidence) ValidateStressWorker(profile contract.Profile) error {
|
|
return e.validate(profile, true)
|
|
}
|
|
|
|
func (e StressEvidence) validate(profile contract.Profile, faultAware bool) error {
|
|
if e.Version != 1 || e.Profile != profile.Name() || e.Seed != contract.DefaultSeed {
|
|
return ErrStressEvidence
|
|
}
|
|
canonical, err := GenerateStressPlan(profile, e.Seed)
|
|
if err != nil || e.Plan.Profile != e.Profile || e.Plan.Seed != e.Seed || !reflect.DeepEqual(e.Plan, canonical) {
|
|
return fmt.Errorf("plan does not match canonical plan: %w", ErrStressEvidence)
|
|
}
|
|
if err := validateStressPreparedBinaries(e.PreparedBinaries); err != nil {
|
|
return err
|
|
}
|
|
if err := e.Quotas.Validate(); err != nil {
|
|
return err
|
|
}
|
|
if err := validateStressWarmups(e.Warmups, profile.AgentCount()); err != nil {
|
|
return err
|
|
}
|
|
if err := validateStressSessions(e.Sessions, canonical.Sessions, profile.ConcurrentSessions()); err != nil {
|
|
return err
|
|
}
|
|
if len(e.Iterations) != profile.Iterations() {
|
|
return fmt.Errorf("iterations=%d want=%d: %w", len(e.Iterations), profile.Iterations(), ErrStressEvidence)
|
|
}
|
|
failed := 0
|
|
for index, iteration := range e.Iterations {
|
|
count, err := validateStressIteration(canonical, iteration, index+1, faultAware)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
failed += count
|
|
}
|
|
if err := validateStressFault(e.FaultTarget, failed, faultAware); err != nil {
|
|
return err
|
|
}
|
|
if profile.Iterations() == 3 {
|
|
if err := ValidateStressSoakTrendForProfile(profile, e.SoakTrend); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if !e.Cleanup.Passed || e.Cleanup.ReceiptCount != 9 || e.Cleanup.FailedReceiptCount != 0 || e.Cleanup.ForcedCleanupCount != 0 || e.Cleanup.ProcessResidue != 0 || e.Cleanup.ProcessGroupResidue != 0 || e.Cleanup.WorkspaceResidue != 0 {
|
|
return fmt.Errorf("cleanup=%+v: %w", e.Cleanup, ErrStressEvidence)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (q StressQuotaEvidence) Validate() error {
|
|
wants := []struct {
|
|
got StressQuotaBoundary
|
|
allow int
|
|
reject int
|
|
}{{q.PATSecond, 10, 11}, {q.PATMinute, 120, 121}, {q.UserStreams, 20, 21}, {q.ServerStreams, 40, 41}}
|
|
for _, want := range wants {
|
|
if want.got.Allowed != want.allow || want.got.Rejected != want.reject || !want.got.AllowedAccepted || !want.got.RejectedDenied {
|
|
return fmt.Errorf("quota=%+v want=%d/%d: %w", want.got, want.allow, want.reject, ErrStressEvidence)
|
|
}
|
|
}
|
|
if q.PathLockStripes != 1024 {
|
|
return fmt.Errorf("path lock stripes=%d: %w", q.PathLockStripes, ErrStressEvidence)
|
|
}
|
|
return nil
|
|
}
|