Files
nezha_domains/integration/agentcompat/internal/scenario/stress_round.go
T
2026-07-20 04:54:03 +00:00

91 lines
3.6 KiB
Go

//go:build linux
package scenario
import (
"errors"
"fmt"
"time"
)
var (
ErrStressOperationSet = errors.New("stress operation evidence set is invalid")
ErrStressLaunchWindow = errors.New("stress operation launch window exceeded one second")
)
const stressLaunchWindow = time.Second
type StressOperationEvidence struct {
ID StressOperationID `json:"id"`
Round int `json:"round"`
Agent StressAgentOrdinal `json:"agent"`
PAT StressPATID `json:"pat_id"`
Kind StressOperationKind `json:"kind"`
LaunchedAt time.Time `json:"launched_at"`
CompletedAt time.Time `json:"completed_at"`
Succeeded bool `json:"succeeded"`
SuccessProof string `json:"success_proof"`
Error string `json:"error,omitempty"`
}
type StressRoundEvidence struct {
Round int `json:"round"`
Operations []StressOperationEvidence `json:"operations"`
}
func ValidateStressRoundEvidence(plan StressRoundPlan, evidence StressRoundEvidence) error {
matched, err := matchStressRoundEvidence(plan, evidence)
if err != nil {
return err
}
for _, operation := range matched {
if !operation.Succeeded || operation.SuccessProof == "" || operation.Error != "" {
return fmt.Errorf("operation %s did not succeed: %w", operation.ID.String(), ErrStressOperationSet)
}
}
return nil
}
func matchStressRoundEvidence(plan StressRoundPlan, evidence StressRoundEvidence) ([]StressOperationEvidence, error) {
if evidence.Round != plan.Round || len(evidence.Operations) != len(plan.Operations) {
return nil, fmt.Errorf("round=%d operations=%d want round=%d operations=%d: %w", evidence.Round, len(evidence.Operations), plan.Round, len(plan.Operations), ErrStressOperationSet)
}
expected := make(map[StressOperationID]struct{}, len(plan.Operations))
for _, operation := range plan.Operations {
expected[operation.ID] = struct{}{}
}
matched := make([]StressOperationEvidence, 0, len(evidence.Operations))
seen := make(map[StressOperationID]struct{}, len(evidence.Operations))
var firstLaunch, lastLaunch time.Time
for index, operation := range evidence.Operations {
planned := plan.Operations[index]
if _, exists := expected[operation.ID]; !exists {
return nil, fmt.Errorf("unexpected operation %s: %w", operation.ID.String(), ErrStressOperationSet)
}
if operation.Round != planned.Round || operation.Agent != planned.Agent || operation.PAT != planned.PAT || operation.Kind != planned.Kind || operation.ID != planned.ID {
return nil, fmt.Errorf("operation %s owner or order mismatch: %w", operation.ID.String(), ErrStressOperationSet)
}
if _, duplicate := seen[operation.ID]; duplicate {
return nil, fmt.Errorf("duplicate operation %s: %w", operation.ID.String(), ErrStressOperationSet)
}
if operation.LaunchedAt.IsZero() || operation.CompletedAt.Before(operation.LaunchedAt) {
return nil, fmt.Errorf("operation %s timing is invalid: %w", operation.ID.String(), ErrStressOperationSet)
}
if operation.Succeeded && operation.SuccessProof == "" {
return nil, fmt.Errorf("operation %s proof is empty: %w", operation.ID.String(), ErrStressOperationSet)
}
seen[operation.ID] = struct{}{}
matched = append(matched, operation)
if firstLaunch.IsZero() || operation.LaunchedAt.Before(firstLaunch) {
firstLaunch = operation.LaunchedAt
}
if lastLaunch.IsZero() || operation.LaunchedAt.After(lastLaunch) {
lastLaunch = operation.LaunchedAt
}
}
if lastLaunch.Sub(firstLaunch) > stressLaunchWindow {
return nil, fmt.Errorf("launch window=%s: %w", lastLaunch.Sub(firstLaunch), ErrStressLaunchWindow)
}
return matched, nil
}