Skip to content

Commit

Permalink
Fix lost error types in oneOf (#658)
Browse files Browse the repository at this point in the history
  • Loading branch information
micronull authored Nov 7, 2022
1 parent 9ea22ae commit d5c7ac5
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 12 deletions.
20 changes: 17 additions & 3 deletions openapi3/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import (
type MultiError []error

func (me MultiError) Error() string {
return spliceErr(" | ", me)
}

func spliceErr(sep string, errs []error) string {
buff := &bytes.Buffer{}
for i, e := range me {
for i, e := range errs {
buff.WriteString(e.Error())
if i != len(me)-1 {
buff.WriteString(" | ")
if i != len(errs)-1 {
buff.WriteString(sep)
}
}
return buff.String()
Expand Down Expand Up @@ -43,3 +47,13 @@ func (me MultiError) As(target interface{}) bool {
}
return false
}

type multiErrorForOneOf MultiError

func (meo multiErrorForOneOf) Error() string {
return spliceErr(" Or ", meo)
}

func (meo multiErrorForOneOf) Unwrap() error {
return MultiError(meo)
}
79 changes: 79 additions & 0 deletions openapi3/issue657_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package openapi3_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/getkin/kin-openapi/openapi3"
)

func TestOneOf_Warning_Errors(t *testing.T) {
t.Parallel()

loader := openapi3.NewLoader()
spec := `
components:
schemas:
Something:
type: object
properties:
field:
title: Some field
oneOf:
- title: First rule
type: string
minLength: 10
maxLength: 10
- title: Second rule
type: string
minLength: 15
maxLength: 15
`[1:]

doc, err := loader.LoadFromData([]byte(spec))
require.NoError(t, err)

tests := [...]struct {
name string
value string
checkErr require.ErrorAssertionFunc
}{
{
name: "valid value",
value: "ABCDE01234",
checkErr: require.NoError,
},
{
name: "valid value",
value: "ABCDE0123456789",
checkErr: require.NoError,
},
{
name: "no valid value",
value: "ABCDE",
checkErr: func(t require.TestingT, err error, i ...interface{}) {
require.Equal(t, "doesn't match schema due to: minimum string length is 10\nSchema:\n {\n \"maxLength\": 10,\n \"minLength\": 10,\n \"title\": \"First rule\",\n \"type\": \"string\"\n }\n\nValue:\n \"ABCDE\"\n Or minimum string length is 15\nSchema:\n {\n \"maxLength\": 15,\n \"minLength\": 15,\n \"title\": \"Second rule\",\n \"type\": \"string\"\n }\n\nValue:\n \"ABCDE\"\n", err.Error())

wErr := &openapi3.MultiError{}
require.ErrorAs(t, err, wErr)

require.Len(t, *wErr, 2)

require.Equal(t, "minimum string length is 10", (*wErr)[0].(*openapi3.SchemaError).Reason)
require.Equal(t, "minimum string length is 15", (*wErr)[1].(*openapi3.SchemaError).Reason)
},
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()

err = doc.Components.Schemas["Something"].Value.Properties["field"].Value.VisitJSON(test.value)

test.checkErr(t, err)
})
}
}
11 changes: 2 additions & 9 deletions openapi3/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val

var (
ok = 0
validationErrors = []error{}
validationErrors = multiErrorForOneOf{}
matchedOneOfIdx = 0
tempValue = value
)
Expand Down Expand Up @@ -955,14 +955,7 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val

if ok != 1 {
if len(validationErrors) > 1 {
errorMessage := ""
for _, err := range validationErrors {
if errorMessage != "" {
errorMessage += " Or "
}
errorMessage += err.Error()
}
return errors.New("doesn't match schema due to: " + errorMessage)
return fmt.Errorf("doesn't match schema due to: %w", validationErrors)
}
if settings.failfast {
return errSchema
Expand Down

0 comments on commit d5c7ac5

Please sign in to comment.