Skip to content
Merged
Show file tree
Hide file tree
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
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