mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-21 18:50:13 +00:00
test(agentcompat): add exact stress scenario
Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
//go:build linux
|
||||
|
||||
package scenario
|
||||
|
||||
import "fmt"
|
||||
|
||||
func validateStressPreparedBinaries(evidence StressPreparedBinaries) error {
|
||||
if evidence.DashboardBuildCount != 1 || !evidence.DashboardPathReused || evidence.AgentBuildCount != 1 || !evidence.AgentPathReused {
|
||||
return fmt.Errorf("prepared binaries=%+v: %w", evidence, ErrStressEvidence)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStressWarmups(warmups []StressWarmupEvidence, agentCount int) error {
|
||||
if len(warmups) != agentCount {
|
||||
return fmt.Errorf("warmups=%d want=%d: %w", len(warmups), agentCount, ErrStressEvidence)
|
||||
}
|
||||
seen := make(map[int]struct{}, len(warmups))
|
||||
for _, warmup := range warmups {
|
||||
if _, duplicate := seen[warmup.Agent.Int()]; duplicate || !warmup.Exec || !warmup.Filesystem || !warmup.Terminal || !warmup.NAT || !warmup.FM {
|
||||
return fmt.Errorf("warmup=%+v: %w", warmup, ErrStressEvidence)
|
||||
}
|
||||
seen[warmup.Agent.Int()] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStressSessions(sessions []StressSessionEvidence, plan []StressSessionPlan, countPerKind int) error {
|
||||
if len(sessions) != countPerKind*3 {
|
||||
return fmt.Errorf("sessions=%d want=%d: %w", len(sessions), countPerKind*3, ErrStressEvidence)
|
||||
}
|
||||
if len(plan) != len(sessions) {
|
||||
return fmt.Errorf("session plan=%d evidence=%d: %w", len(plan), len(sessions), ErrStressEvidence)
|
||||
}
|
||||
expected := make(map[StressSessionID]StressSessionPlan, len(plan))
|
||||
for _, session := range plan {
|
||||
expected[session.ID] = session
|
||||
}
|
||||
counts := make(map[StressSessionKind]int, 3)
|
||||
seen := make(map[StressSessionID]struct{}, len(sessions))
|
||||
for _, session := range sessions {
|
||||
planned, exists := expected[session.ID]
|
||||
_, duplicate := seen[session.ID]
|
||||
if !exists || planned.Kind != session.Kind || duplicate || !session.Succeeded {
|
||||
return fmt.Errorf("session=%+v: %w", session, ErrStressEvidence)
|
||||
}
|
||||
seen[session.ID] = struct{}{}
|
||||
counts[session.Kind]++
|
||||
}
|
||||
for _, kind := range []StressSessionKind{StressSessionTerminal, StressSessionNAT, StressSessionFM} {
|
||||
if counts[kind] != countPerKind {
|
||||
return fmt.Errorf("session kind=%s count=%d want=%d: %w", kind, counts[kind], countPerKind, ErrStressEvidence)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateStressIteration(plan StressPlan, evidence StressIterationEvidence, iteration int, faultAware bool) (int, error) {
|
||||
if evidence.Iteration != iteration || len(evidence.Rounds) != len(plan.Rounds) || len(evidence.Resources) != 1+canonicalAgentCount(plan) {
|
||||
return 0, fmt.Errorf("iteration=%+v: %w", evidence, ErrStressEvidence)
|
||||
}
|
||||
failed := 0
|
||||
for index, round := range evidence.Rounds {
|
||||
matched, err := matchStressRoundEvidence(plan.Rounds[index], round)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, operation := range matched {
|
||||
if !operation.Succeeded || operation.Error != "" {
|
||||
failed++
|
||||
if !faultAware || !isStressFaultOperation(plan.Rounds[index], operation, iteration) {
|
||||
return 0, fmt.Errorf("unexpected failed operation=%s: %w", operation.ID.String(), ErrStressFault)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := validateStressResourceIdentities(plan, evidence.Resources); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, windows := range evidence.Resources {
|
||||
if _, err := EvaluateStressResource(windows); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return failed, nil
|
||||
}
|
||||
|
||||
func validateStressFault(target *StressFaultTarget, failed int, faultAware bool) error {
|
||||
if !faultAware {
|
||||
if target != nil || failed != 0 {
|
||||
return ErrStressFault
|
||||
}
|
||||
return nil
|
||||
}
|
||||
want := StressWorkerFaultTarget()
|
||||
if target == nil || *target != want || failed != 1 {
|
||||
return fmt.Errorf("target=%+v failed=%d want=%+v/1: %w", target, failed, want, ErrStressFault)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isStressFaultOperation(plan StressRoundPlan, evidence StressOperationEvidence, iteration int) bool {
|
||||
target := StressWorkerFaultTarget()
|
||||
if iteration != target.Iteration || plan.Round != target.Round {
|
||||
return false
|
||||
}
|
||||
for _, operation := range plan.Operations {
|
||||
if operation.ID == evidence.ID {
|
||||
return operation.Agent == target.Agent && operation.Kind == target.Kind
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func planAgentCount(plan StressPlan) int {
|
||||
return canonicalAgentCount(plan)
|
||||
}
|
||||
|
||||
func canonicalAgentCount(plan StressPlan) int {
|
||||
if len(plan.Rounds) == 0 {
|
||||
return 0
|
||||
}
|
||||
return len(plan.Rounds[0].Operations) / 2
|
||||
}
|
||||
|
||||
func validateStressResourceIdentities(plan StressPlan, resources []StressProcessWindows) error {
|
||||
wantAgents := planAgentCount(plan)
|
||||
if len(resources) != wantAgents+1 {
|
||||
return fmt.Errorf("resources=%d want=%d: %w", len(resources), wantAgents+1, ErrStressEvidence)
|
||||
}
|
||||
dashboardCount := 0
|
||||
seenAgents := make(map[int]struct{}, wantAgents)
|
||||
for _, resource := range resources {
|
||||
switch resource.Process.Kind {
|
||||
case StressProcessDashboard:
|
||||
dashboardCount++
|
||||
case StressProcessAgent:
|
||||
ordinal := resource.Process.Agent.Int()
|
||||
if ordinal < 1 || ordinal > wantAgents {
|
||||
return fmt.Errorf("unknown agent ordinal=%d: %w", ordinal, ErrStressEvidence)
|
||||
}
|
||||
if _, duplicate := seenAgents[ordinal]; duplicate {
|
||||
return fmt.Errorf("duplicate agent ordinal=%d: %w", ordinal, ErrStressEvidence)
|
||||
}
|
||||
seenAgents[ordinal] = struct{}{}
|
||||
default:
|
||||
return fmt.Errorf("unknown process kind=%q: %w", resource.Process.Kind, ErrStressEvidence)
|
||||
}
|
||||
}
|
||||
if dashboardCount != 1 || len(seenAgents) != wantAgents {
|
||||
return fmt.Errorf("dashboard=%d agents=%d want=1/%d: %w", dashboardCount, len(seenAgents), wantAgents, ErrStressEvidence)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user