Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed: Reworded syntax error messages to be clearer #838

Merged
merged 1 commit into from
Sep 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 35 additions & 23 deletions resource/gomega.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/goss-org/goss/matchers"
"github.com/samber/lo"
)

func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
Expand All @@ -16,7 +17,7 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
case bool:
return matchers.Equal(x), nil
case []any:
subMatchers, err := sliceToGomega(x)
subMatchers, err := sliceToGomega(x, "")
if err != nil {
return nil, err
}
Expand All @@ -28,54 +29,59 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
}
matcher = sanitizeExpectedValue(matcher)
if matcher == nil {
return nil, fmt.Errorf("Missing Required Attribute")
return nil, fmt.Errorf("Syntax Error: Missing required attribute")
}
matcherMap, ok := matcher.(map[string]any)
if !ok {
panic(fmt.Sprintf("Unexpected matcher type: %T\n\n", matcher))
return nil, invalidArgSyntaxError("matcher", "map", matcher)
//panic(fmt.Sprintf("Syntax Error: Unexpected matcher type: %T\n\n", matcher))
}
var matchType string
var value any
for matchType, value = range matcherMap {
break
keys := lo.Keys(matcherMap)
if len(keys) > 1 {
return nil, fmt.Errorf("Syntax Error: Invalid matcher configuration. At a given nesting level, only one matcher is allowed. Found multiple matchers: %q", keys)
}
matchType := keys[0]
value := matcherMap[matchType]
switch matchType {
case "equal":
return matchers.Equal(value), nil
case "have-prefix":
v, isStr := value.(string)
if !isStr {
return nil, fmt.Errorf("have-prefix: syntax error: incorrect expectation type. expected string, got: %#v", value)
return nil, invalidArgSyntaxError("have-prefix", "string", value)
}
return matchers.WithSafeTransform(matchers.ToString{}, matchers.HavePrefix(v)), nil
case "have-suffix":
v, isStr := value.(string)
if !isStr {
return nil, fmt.Errorf("have-suffix: syntax error: incorrect expectation type. expected string, got: %#v", value)
return nil, invalidArgSyntaxError("have-suffix", "string", value)
}
return matchers.WithSafeTransform(matchers.ToString{}, matchers.HaveSuffix(v)), nil
case "match-regexp":
v, isStr := value.(string)
if !isStr {
return nil, fmt.Errorf("match-regexp: syntax error: incorrect expectation type. expected string, got: %#v", value)
return nil, invalidArgSyntaxError("match-regexp", "string", value)
}
return matchers.WithSafeTransform(matchers.ToString{}, matchers.MatchRegexp(v)), nil
case "contain-substring":
v, isStr := value.(string)
if !isStr {
return nil, fmt.Errorf("contain-substring: syntax error: incorrect expectation type. expected string, got: %#v", value)
return nil, invalidArgSyntaxError("contain-substring", "string", value)

}
return matchers.WithSafeTransform(matchers.ToString{}, matchers.ContainSubstring(v)), nil
case "have-len":
v, isFloat := value.(float64)
if !isFloat {
return nil, fmt.Errorf("have-len: syntax error: incorrect expectation type. expected numeric, got: %#v", value)
return nil, invalidArgSyntaxError("have-len", "numeric", value)

}
return matchers.HaveLen(int(v)), nil
case "have-patterns":
_, isArr := value.([]any)
if !isArr {
return nil, fmt.Errorf("have-patterns: syntax error: incorrect expectation type. expected array, got: %#v", value)
return nil, invalidArgSyntaxError("have-patterns", "array", value)

}
return matchers.WithSafeTransform(matchers.ToString{}, matchers.HavePatterns(value)), nil
case "have-key":
Expand All @@ -88,15 +94,16 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
switch value.(type) {
case map[string]any, string, float64:
default:
return nil, fmt.Errorf("contain-element: syntax error: incorrect expectation type. expected matcher or value, got: %#v", value)
return nil, invalidArgSyntaxError("contain-element", "matcher, string or numeric", value)

}
subMatcher, err := matcherToGomegaMatcher(value)
if err != nil {
return nil, err
}
return matchers.WithSafeTransform(matchers.ToArray{}, matchers.ContainElement(subMatcher)), nil
case "contain-elements":
subMatchers, err := sliceToGomega(value)
subMatchers, err := sliceToGomega(value, "contains-elements")
if err != nil {
return nil, err
}
Expand All @@ -112,7 +119,7 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
}
return matchers.Not(subMatcher), nil
case "consist-of":
subMatchers, err := sliceToGomega(value)
subMatchers, err := sliceToGomega(value, "consist-of")
if err != nil {
return nil, err
}
Expand All @@ -122,13 +129,13 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
}
return matchers.ConsistOf(interfaceSlice...), nil
case "and":
subMatchers, err := sliceToGomega(value)
subMatchers, err := sliceToGomega(value, "and")
if err != nil {
return nil, err
}
return matchers.And(subMatchers...), nil
case "or":
subMatchers, err := sliceToGomega(value)
subMatchers, err := sliceToGomega(value, "or")
if err != nil {
return nil, err
}
Expand All @@ -139,14 +146,15 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
case "semver-constraint":
v, isStr := value.(string)
if !isStr {
return nil, fmt.Errorf("semver-contstraint: syntax error: incorrect expectation type. expected string, got: %#v", value)
return nil, invalidArgSyntaxError("semver-constraint", "string", value)

}
return matchers.BeSemverConstraint(v), nil
case "gjson":
var subMatchers []matchers.GossMatcher
valueI, ok := value.(map[string]any)
if !ok {
return nil, fmt.Errorf("Matcher expected map, got: %t", value)
return nil, invalidArgSyntaxError("gjson", "map", value)
}
for key, val := range valueI {
subMatcher, err := matcherToGomegaMatcher(val)
Expand All @@ -158,15 +166,15 @@ func matcherToGomegaMatcher(matcher any) (matchers.GossMatcher, error) {
}
return matchers.And(subMatchers...), nil
default:
return nil, fmt.Errorf("Unknown matcher: %s", matchType)
return nil, fmt.Errorf("Syntax Error: Unknown matcher: %s", matchType)

}
}

func sliceToGomega(value any) ([]matchers.GossMatcher, error) {
func sliceToGomega(value any, name string) ([]matchers.GossMatcher, error) {
valueI, ok := value.([]any)
if !ok {
return nil, fmt.Errorf("Matcher expected array, got: %t", value)
return nil, invalidArgSyntaxError(name, "array", value)
}
var subMatchers []matchers.GossMatcher
for _, v := range valueI {
Expand Down Expand Up @@ -198,3 +206,7 @@ func sanitizeExpectedValue(i any) any {
}
return i
}

func invalidArgSyntaxError(name, expected string, value any) error {
return fmt.Errorf("Syntax Error: Invalid '%s' argument. Expected %s value, but received: %q", name, expected, value)
}