Skip to content

Commit

Permalink
improve schema error reason message and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ori-shalom committed Jan 22, 2023
1 parent 5c0555e commit a9d5d87
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 47 deletions.
2 changes: 1 addition & 1 deletion openapi3/issue136_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ components:
},
{
dflt: `1`,
err: "invalid components: invalid schema default: field must be set to string or not be present",
err: "invalid components: invalid schema default: value must be a string",
},
} {
t.Run(testcase.dflt, func(t *testing.T) {
Expand Down
279 changes: 279 additions & 0 deletions openapi3/issue735_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
package openapi3

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"
)

type testCase struct {
name string
schema *Schema
value interface{}
extraNotContains []interface{}
options []SchemaValidationOption
}

func TestIssue735(t *testing.T) {
DefineStringFormat("uuid", FormatOfStringForUUIDOfRFC4122)
DefineStringFormat("email", FormatOfStringForEmail)
DefineIPv4Format()
DefineIPv6Format()

testCases := []testCase{
{
name: "type string",
schema: NewStringSchema(),
value: 42,
},
{
name: "type boolean",
schema: NewBoolSchema(),
value: 42,
},
{
name: "type integer",
schema: NewIntegerSchema(),
value: "foo",
},
{
name: "type number",
schema: NewFloat64Schema(),
value: "foo",
},
{
name: "type array",
schema: NewArraySchema(),
value: 42,
},
{
name: "type object",
schema: NewObjectSchema(),
value: 42,
},
{
name: "min",
schema: NewSchema().WithMin(100),
value: 42,
},
{
name: "max",
schema: NewSchema().WithMax(0),
value: 42,
},
{
name: "exclusive min",
schema: NewSchema().WithMin(100).WithExclusiveMin(true),
value: 42,
},
{
name: "exclusive max",
schema: NewSchema().WithMax(0).WithExclusiveMax(true),
value: 42,
},
{
name: "multiple of",
schema: &Schema{MultipleOf: Float64Ptr(5.0)},
value: 42,
},
{
name: "enum",
schema: NewSchema().WithEnum(3, 5),
value: 42,
},
{
name: "min length",
schema: NewSchema().WithMinLength(100),
value: "foo",
},
{
name: "max length",
schema: NewSchema().WithMaxLength(0),
value: "foo",
},
{
name: "pattern",
schema: NewSchema().WithPattern("[0-9]"),
value: "foo",
},
{
name: "items",
schema: NewSchema().WithItems(NewStringSchema()),
value: []interface{}{42},
extraNotContains: []interface{}{42},
},
{
name: "min items",
schema: NewSchema().WithMinItems(100),
value: []interface{}{42},
extraNotContains: []interface{}{42},
},
{
name: "max items",
schema: NewSchema().WithMaxItems(0),
value: []interface{}{42},
extraNotContains: []interface{}{42},
},
{
name: "unique items",
schema: NewSchema().WithUniqueItems(true),
value: []interface{}{42, 42},
extraNotContains: []interface{}{42},
},
{
name: "min properties",
schema: NewSchema().WithMinProperties(100),
value: map[string]interface{}{"foo": 42},
extraNotContains: []interface{}{42},
},
{
name: "max properties",
schema: NewSchema().WithMaxProperties(0),
value: map[string]interface{}{"foo": 42},
extraNotContains: []interface{}{42},
},
{
name: "additional properties other schema type",
schema: NewSchema().WithAdditionalProperties(NewStringSchema()),
value: map[string]interface{}{"foo": 42},
extraNotContains: []interface{}{42},
},
// TODO: uncomment when https://github.com/getkin/kin-openapi/pull/747 is merged
//{
// name: "additional properties false",
// schema: &Schema{AdditionalProperties: AdditionalProperties{
// Has: BoolPtr(false),
// }},
// value: map[string]interface{}erface{}{"foo": 42},
// extraNotContains: []interface{}{42},
//},
{
name: "invalid properties schema",
schema: NewSchema().WithProperties(map[string]*Schema{
"foo": NewStringSchema(),
}),
value: map[string]interface{}{"foo": 42},
extraNotContains: []interface{}{42},
},
// TODO: uncomment when https://github.com/getkin/kin-openapi/issues/502 is fixed
//{
// name: "read only properties",
// schema: NewSchema().WithProperties(map[string]*Schema{
// "foo": {ReadOnly: true},
// }).WithNoAdditionalProperties(),
// value: map[string]interface{}{"foo": 42},
// extraNotContains: []interface{}{42},
// options: []SchemaValidationOption{VisitAsRequest()},
//},
//{
// name: "write only properties",
// schema: NewSchema().WithProperties(map[string]*Schema{
// "foo": {WriteOnly: true},
// }).WithNoAdditionalProperties(),
// value: map[string]interface{}{"foo": 42},
// extraNotContains: []interface{}{42},
// options: []SchemaValidationOption{VisitAsResponse()},
//},
{
name: "required properties",
schema: &Schema{
Properties: Schemas{
"bar": NewStringSchema().NewRef(),
},
Required: []string{"bar"},
},
value: map[string]interface{}{"foo": 42},
extraNotContains: []interface{}{42},
},
{
name: "one of (matches more then one)",
schema: NewOneOfSchema(
&Schema{MultipleOf: Float64Ptr(6)},
&Schema{MultipleOf: Float64Ptr(7)},
),
value: 42,
},
{
name: "one of (no matches)",
schema: NewOneOfSchema(
&Schema{MultipleOf: Float64Ptr(5)},
&Schema{MultipleOf: Float64Ptr(10)},
),
value: 42,
},
{
name: "any of",
schema: NewAnyOfSchema(
&Schema{MultipleOf: Float64Ptr(5)},
&Schema{MultipleOf: Float64Ptr(10)},
),
value: 42,
},
{
name: "all of (match some)",
schema: NewAllOfSchema(
&Schema{MultipleOf: Float64Ptr(6)},
&Schema{MultipleOf: Float64Ptr(5)},
),
value: 42,
},
{
name: "all of (no match)",
schema: NewAllOfSchema(
&Schema{MultipleOf: Float64Ptr(10)},
&Schema{MultipleOf: Float64Ptr(5)},
),
value: 42,
},
{
name: "uuid format",
schema: NewUUIDSchema(),
value: "foo",
},
{
name: "date time format",
schema: NewDateTimeSchema(),
value: "foo",
},
{
name: "date format",
schema: NewSchema().WithFormat("date"),
value: "foo",
},
{
name: "ipv4 format",
schema: NewSchema().WithFormat("ipv4"),
value: "foo",
},
{
name: "ipv6 format",
schema: NewSchema().WithFormat("ipv6"),
value: "foo",
},
{
name: "email format",
schema: NewSchema().WithFormat("email"),
value: "foo",
},
{
name: "byte format",
schema: NewBytesSchema(),
value: "foo!",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := tc.schema.VisitJSON(tc.value, tc.options...)
var schemaError = &SchemaError{}
require.Error(t, err)
require.ErrorAs(t, err, &schemaError)
require.NotZero(t, schemaError.Reason)
require.NotContains(t, schemaError.Reason, fmt.Sprint(tc.value))
for _, extra := range tc.extraNotContains {
require.NotContains(t, schemaError.Reason, fmt.Sprint(extra))
}
})
}
}

0 comments on commit a9d5d87

Please sign in to comment.