mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 17:50:12 +00:00
106 lines
3.4 KiB
Go
106 lines
3.4 KiB
Go
package evidence
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/nezhahq/nezha/integration/agentcompat/internal/contract"
|
|
)
|
|
|
|
type ScenarioResult struct {
|
|
Name string `json:"name"`
|
|
Passed bool `json:"passed"`
|
|
Assertions []Assertion `json:"assertions,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
type Assertion struct {
|
|
Name string `json:"name"`
|
|
Passed bool `json:"passed"`
|
|
Details string `json:"details,omitempty"`
|
|
}
|
|
|
|
type Results struct {
|
|
Profile string `json:"profile"`
|
|
Passed bool `json:"passed"`
|
|
Scenarios []ScenarioResult `json:"scenarios"`
|
|
}
|
|
|
|
func (results Results) Validate() error {
|
|
if results.Profile == "" || len(results.Scenarios) == 0 {
|
|
return fmt.Errorf("results fields are incomplete")
|
|
}
|
|
if _, err := contract.ProfileByName(results.Profile); err != nil {
|
|
return fmt.Errorf("results profile is invalid: %w", err)
|
|
}
|
|
allPassed := true
|
|
seenScenarios := make(map[string]struct{}, len(results.Scenarios))
|
|
for _, scenario := range results.Scenarios {
|
|
if _, err := contract.NewScenario(scenario.Name); err != nil {
|
|
return fmt.Errorf("scenario name is invalid: %w", err)
|
|
}
|
|
if _, exists := seenScenarios[scenario.Name]; exists {
|
|
return fmt.Errorf("scenario name is duplicated")
|
|
}
|
|
seenScenarios[scenario.Name] = struct{}{}
|
|
if len(scenario.Assertions) == 0 {
|
|
return fmt.Errorf("scenario must contain assertions")
|
|
}
|
|
assertionsPassed := true
|
|
seenAssertions := make(map[string]struct{}, len(scenario.Assertions))
|
|
for _, assertion := range scenario.Assertions {
|
|
if assertion.Name == "" {
|
|
return fmt.Errorf("assertion name is required")
|
|
}
|
|
if _, exists := seenAssertions[assertion.Name]; exists {
|
|
return fmt.Errorf("assertion name is duplicated")
|
|
}
|
|
seenAssertions[assertion.Name] = struct{}{}
|
|
assertionsPassed = assertionsPassed && assertion.Passed
|
|
}
|
|
if scenario.Passed != assertionsPassed {
|
|
return fmt.Errorf("scenario pass state is inconsistent with assertions")
|
|
}
|
|
if !scenario.Passed {
|
|
if scenario.Error == "" {
|
|
return fmt.Errorf("failed scenario error is required")
|
|
}
|
|
allPassed = false
|
|
} else if scenario.Error != "" {
|
|
return fmt.Errorf("passed scenario cannot contain an error")
|
|
}
|
|
}
|
|
if results.Passed != allPassed {
|
|
return fmt.Errorf("results pass state is inconsistent")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func MarshalResults(results Results) ([]byte, error) {
|
|
if err := results.Validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
return json.Marshal(results)
|
|
}
|
|
|
|
func (results Results) MarshalJSON() ([]byte, error) {
|
|
type resultsWire Results
|
|
redacted := resultsWire{Profile: results.Profile, Passed: results.Passed, Scenarios: make([]ScenarioResult, 0, len(results.Scenarios))}
|
|
for _, scenario := range results.Scenarios {
|
|
assertions := make([]Assertion, 0, len(scenario.Assertions))
|
|
for _, assertion := range scenario.Assertions {
|
|
assertions = append(assertions, Assertion{Name: assertion.Name, Passed: assertion.Passed, Details: Redact(assertion.Details)})
|
|
}
|
|
redacted.Scenarios = append(redacted.Scenarios, ScenarioResult{Name: scenario.Name, Passed: scenario.Passed, Assertions: assertions, Error: Redact(scenario.Error)})
|
|
}
|
|
return json.Marshal(redacted)
|
|
}
|
|
|
|
func scenarioResultNames(scenarios []ScenarioResult) []string {
|
|
names := make([]string, 0, len(scenarios))
|
|
for _, scenario := range scenarios {
|
|
names = append(names, scenario.Name)
|
|
}
|
|
return names
|
|
}
|