Pulse/internal/models/profile_validation_additional_test.go
2026-03-18 16:06:30 +00:00

184 lines
5.6 KiB
Go

package models
import (
"strings"
"testing"
)
func TestValidationErrorError(t *testing.T) {
err := ValidationError{Key: "cpu_threshold", Message: "invalid"}
if got := err.Error(); got != "cpu_threshold: invalid" {
t.Fatalf("Error() = %q, want cpu_threshold: invalid", got)
}
}
func TestProfileValidatorValidateValue_StringPatternBranches(t *testing.T) {
validator := NewProfileValidator()
matchDef := ConfigKeyDefinition{
Key: "report_ip",
Type: ConfigTypeString,
Pattern: "^[a-z]+$",
}
if err := validator.validateValue(matchDef, "abc"); err != nil {
t.Fatalf("validateValue() unexpected error for matching pattern: %v", err)
}
if err := validator.validateValue(matchDef, "ABC"); err == nil || !strings.Contains(err.Error(), "does not match pattern") {
t.Fatalf("validateValue() expected pattern mismatch error, got: %v", err)
}
invalidPatternDef := ConfigKeyDefinition{
Key: "report_ip",
Type: ConfigTypeString,
Pattern: "[",
}
if err := validator.validateValue(invalidPatternDef, "abc"); err == nil || !strings.Contains(err.Error(), "invalid pattern in definition") {
t.Fatalf("validateValue() expected invalid pattern definition error, got: %v", err)
}
}
func TestProfileValidatorValidateValue_IntTypeBranches(t *testing.T) {
validator := NewProfileValidator()
min := 1.0
max := 10.0
def := ConfigKeyDefinition{
Key: "workers",
Type: ConfigTypeInt,
Min: &min,
Max: &max,
}
tests := []struct {
name string
value interface{}
wantErrSub string
}{
{name: "int in range", value: 5},
{name: "int64 in range", value: int64(6)},
{name: "integral float64 in range", value: 7.0},
{name: "float64 not integral", value: 7.5, wantErrSub: "expected integer, got float"},
{name: "below min", value: 0, wantErrSub: "below minimum"},
{name: "above max", value: 11, wantErrSub: "exceeds maximum"},
{name: "wrong type", value: true, wantErrSub: "expected integer, got bool"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := validator.validateValue(def, tc.value)
if tc.wantErrSub == "" && err != nil {
t.Fatalf("validateValue() unexpected error: %v", err)
}
if tc.wantErrSub != "" {
if err == nil {
t.Fatalf("validateValue() expected error containing %q, got nil", tc.wantErrSub)
}
if !strings.Contains(err.Error(), tc.wantErrSub) {
t.Fatalf("validateValue() error %q does not contain %q", err.Error(), tc.wantErrSub)
}
}
})
}
}
func TestProfileValidatorValidateValue_FloatTypeBranches(t *testing.T) {
validator := NewProfileValidator()
min := 0.5
max := 2.5
def := ConfigKeyDefinition{
Key: "threshold",
Type: ConfigTypeFloat,
Min: &min,
Max: &max,
}
tests := []struct {
name string
value interface{}
wantErrSub string
}{
{name: "int in range", value: 1},
{name: "int64 in range", value: int64(2)},
{name: "float64 in range", value: 1.5},
{name: "below min", value: 0.25, wantErrSub: "below minimum"},
{name: "above max", value: 3.0, wantErrSub: "exceeds maximum"},
{name: "wrong type", value: "1.2", wantErrSub: "expected number, got string"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := validator.validateValue(def, tc.value)
if tc.wantErrSub == "" && err != nil {
t.Fatalf("validateValue() unexpected error: %v", err)
}
if tc.wantErrSub != "" {
if err == nil {
t.Fatalf("validateValue() expected error containing %q, got nil", tc.wantErrSub)
}
if !strings.Contains(err.Error(), tc.wantErrSub) {
t.Fatalf("validateValue() error %q does not contain %q", err.Error(), tc.wantErrSub)
}
}
})
}
}
func TestProfileValidatorValidateValue_EnumCaseInsensitive(t *testing.T) {
validator := NewProfileValidator()
def := ConfigKeyDefinition{
Key: "docker_runtime",
Type: ConfigTypeEnum,
Enum: []string{"auto", "docker"},
}
if err := validator.validateValue(def, "DOCKER"); err != nil {
t.Fatalf("validateValue() expected case-insensitive enum match, got: %v", err)
}
if err := validator.validateValue(def, "podman"); err == nil || !strings.Contains(err.Error(), "value must be one of") {
t.Fatalf("validateValue() expected enum error for unsupported value, got: %v", err)
}
}
func TestProfileValidatorValidate_RequiredKeyBranches(t *testing.T) {
validator := NewProfileValidator()
validator.keyDefs = map[string]ConfigKeyDefinition{
"required_key": {
Key: "required_key",
Type: ConfigTypeString,
Required: true,
},
"optional_key": {
Key: "optional_key",
Type: ConfigTypeString,
Required: false,
},
}
missing := validator.Validate(AgentConfigMap{})
if missing.Valid {
t.Fatalf("Validate() expected missing required key to fail")
}
if len(missing.Errors) != 1 || missing.Errors[0].Key != "required_key" || !strings.Contains(missing.Errors[0].Message, "Required configuration key is missing") {
t.Fatalf("Validate() expected required-key-missing error, got: %+v", missing.Errors)
}
nilRequired := validator.Validate(AgentConfigMap{
"required_key": nil,
"optional_key": nil,
})
if nilRequired.Valid {
t.Fatalf("Validate() expected nil required key value to fail")
}
if len(nilRequired.Errors) != 1 || nilRequired.Errors[0].Key != "required_key" || !strings.Contains(nilRequired.Errors[0].Message, "value cannot be null") {
t.Fatalf("Validate() expected nil-required-value error, got: %+v", nilRequired.Errors)
}
valid := validator.Validate(AgentConfigMap{
"required_key": "set",
"optional_key": nil,
})
if !valid.Valid {
t.Fatalf("Validate() expected valid required key config to pass, got errors: %+v", valid.Errors)
}
}