Skip to content

Commit a9d5d87

Browse files
committed
improve schema error reason message and add tests
1 parent 5c0555e commit a9d5d87

File tree

8 files changed

+355
-47
lines changed

8 files changed

+355
-47
lines changed

openapi3/issue136_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ components:
3131
},
3232
{
3333
dflt: `1`,
34-
err: "invalid components: invalid schema default: field must be set to string or not be present",
34+
err: "invalid components: invalid schema default: value must be a string",
3535
},
3636
} {
3737
t.Run(testcase.dflt, func(t *testing.T) {

openapi3/issue735_test.go

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
package openapi3
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
type testCase struct {
11+
name string
12+
schema *Schema
13+
value interface{}
14+
extraNotContains []interface{}
15+
options []SchemaValidationOption
16+
}
17+
18+
func TestIssue735(t *testing.T) {
19+
DefineStringFormat("uuid", FormatOfStringForUUIDOfRFC4122)
20+
DefineStringFormat("email", FormatOfStringForEmail)
21+
DefineIPv4Format()
22+
DefineIPv6Format()
23+
24+
testCases := []testCase{
25+
{
26+
name: "type string",
27+
schema: NewStringSchema(),
28+
value: 42,
29+
},
30+
{
31+
name: "type boolean",
32+
schema: NewBoolSchema(),
33+
value: 42,
34+
},
35+
{
36+
name: "type integer",
37+
schema: NewIntegerSchema(),
38+
value: "foo",
39+
},
40+
{
41+
name: "type number",
42+
schema: NewFloat64Schema(),
43+
value: "foo",
44+
},
45+
{
46+
name: "type array",
47+
schema: NewArraySchema(),
48+
value: 42,
49+
},
50+
{
51+
name: "type object",
52+
schema: NewObjectSchema(),
53+
value: 42,
54+
},
55+
{
56+
name: "min",
57+
schema: NewSchema().WithMin(100),
58+
value: 42,
59+
},
60+
{
61+
name: "max",
62+
schema: NewSchema().WithMax(0),
63+
value: 42,
64+
},
65+
{
66+
name: "exclusive min",
67+
schema: NewSchema().WithMin(100).WithExclusiveMin(true),
68+
value: 42,
69+
},
70+
{
71+
name: "exclusive max",
72+
schema: NewSchema().WithMax(0).WithExclusiveMax(true),
73+
value: 42,
74+
},
75+
{
76+
name: "multiple of",
77+
schema: &Schema{MultipleOf: Float64Ptr(5.0)},
78+
value: 42,
79+
},
80+
{
81+
name: "enum",
82+
schema: NewSchema().WithEnum(3, 5),
83+
value: 42,
84+
},
85+
{
86+
name: "min length",
87+
schema: NewSchema().WithMinLength(100),
88+
value: "foo",
89+
},
90+
{
91+
name: "max length",
92+
schema: NewSchema().WithMaxLength(0),
93+
value: "foo",
94+
},
95+
{
96+
name: "pattern",
97+
schema: NewSchema().WithPattern("[0-9]"),
98+
value: "foo",
99+
},
100+
{
101+
name: "items",
102+
schema: NewSchema().WithItems(NewStringSchema()),
103+
value: []interface{}{42},
104+
extraNotContains: []interface{}{42},
105+
},
106+
{
107+
name: "min items",
108+
schema: NewSchema().WithMinItems(100),
109+
value: []interface{}{42},
110+
extraNotContains: []interface{}{42},
111+
},
112+
{
113+
name: "max items",
114+
schema: NewSchema().WithMaxItems(0),
115+
value: []interface{}{42},
116+
extraNotContains: []interface{}{42},
117+
},
118+
{
119+
name: "unique items",
120+
schema: NewSchema().WithUniqueItems(true),
121+
value: []interface{}{42, 42},
122+
extraNotContains: []interface{}{42},
123+
},
124+
{
125+
name: "min properties",
126+
schema: NewSchema().WithMinProperties(100),
127+
value: map[string]interface{}{"foo": 42},
128+
extraNotContains: []interface{}{42},
129+
},
130+
{
131+
name: "max properties",
132+
schema: NewSchema().WithMaxProperties(0),
133+
value: map[string]interface{}{"foo": 42},
134+
extraNotContains: []interface{}{42},
135+
},
136+
{
137+
name: "additional properties other schema type",
138+
schema: NewSchema().WithAdditionalProperties(NewStringSchema()),
139+
value: map[string]interface{}{"foo": 42},
140+
extraNotContains: []interface{}{42},
141+
},
142+
// TODO: uncomment when https://github.com/getkin/kin-openapi/pull/747 is merged
143+
//{
144+
// name: "additional properties false",
145+
// schema: &Schema{AdditionalProperties: AdditionalProperties{
146+
// Has: BoolPtr(false),
147+
// }},
148+
// value: map[string]interface{}erface{}{"foo": 42},
149+
// extraNotContains: []interface{}{42},
150+
//},
151+
{
152+
name: "invalid properties schema",
153+
schema: NewSchema().WithProperties(map[string]*Schema{
154+
"foo": NewStringSchema(),
155+
}),
156+
value: map[string]interface{}{"foo": 42},
157+
extraNotContains: []interface{}{42},
158+
},
159+
// TODO: uncomment when https://github.com/getkin/kin-openapi/issues/502 is fixed
160+
//{
161+
// name: "read only properties",
162+
// schema: NewSchema().WithProperties(map[string]*Schema{
163+
// "foo": {ReadOnly: true},
164+
// }).WithNoAdditionalProperties(),
165+
// value: map[string]interface{}{"foo": 42},
166+
// extraNotContains: []interface{}{42},
167+
// options: []SchemaValidationOption{VisitAsRequest()},
168+
//},
169+
//{
170+
// name: "write only properties",
171+
// schema: NewSchema().WithProperties(map[string]*Schema{
172+
// "foo": {WriteOnly: true},
173+
// }).WithNoAdditionalProperties(),
174+
// value: map[string]interface{}{"foo": 42},
175+
// extraNotContains: []interface{}{42},
176+
// options: []SchemaValidationOption{VisitAsResponse()},
177+
//},
178+
{
179+
name: "required properties",
180+
schema: &Schema{
181+
Properties: Schemas{
182+
"bar": NewStringSchema().NewRef(),
183+
},
184+
Required: []string{"bar"},
185+
},
186+
value: map[string]interface{}{"foo": 42},
187+
extraNotContains: []interface{}{42},
188+
},
189+
{
190+
name: "one of (matches more then one)",
191+
schema: NewOneOfSchema(
192+
&Schema{MultipleOf: Float64Ptr(6)},
193+
&Schema{MultipleOf: Float64Ptr(7)},
194+
),
195+
value: 42,
196+
},
197+
{
198+
name: "one of (no matches)",
199+
schema: NewOneOfSchema(
200+
&Schema{MultipleOf: Float64Ptr(5)},
201+
&Schema{MultipleOf: Float64Ptr(10)},
202+
),
203+
value: 42,
204+
},
205+
{
206+
name: "any of",
207+
schema: NewAnyOfSchema(
208+
&Schema{MultipleOf: Float64Ptr(5)},
209+
&Schema{MultipleOf: Float64Ptr(10)},
210+
),
211+
value: 42,
212+
},
213+
{
214+
name: "all of (match some)",
215+
schema: NewAllOfSchema(
216+
&Schema{MultipleOf: Float64Ptr(6)},
217+
&Schema{MultipleOf: Float64Ptr(5)},
218+
),
219+
value: 42,
220+
},
221+
{
222+
name: "all of (no match)",
223+
schema: NewAllOfSchema(
224+
&Schema{MultipleOf: Float64Ptr(10)},
225+
&Schema{MultipleOf: Float64Ptr(5)},
226+
),
227+
value: 42,
228+
},
229+
{
230+
name: "uuid format",
231+
schema: NewUUIDSchema(),
232+
value: "foo",
233+
},
234+
{
235+
name: "date time format",
236+
schema: NewDateTimeSchema(),
237+
value: "foo",
238+
},
239+
{
240+
name: "date format",
241+
schema: NewSchema().WithFormat("date"),
242+
value: "foo",
243+
},
244+
{
245+
name: "ipv4 format",
246+
schema: NewSchema().WithFormat("ipv4"),
247+
value: "foo",
248+
},
249+
{
250+
name: "ipv6 format",
251+
schema: NewSchema().WithFormat("ipv6"),
252+
value: "foo",
253+
},
254+
{
255+
name: "email format",
256+
schema: NewSchema().WithFormat("email"),
257+
value: "foo",
258+
},
259+
{
260+
name: "byte format",
261+
schema: NewBytesSchema(),
262+
value: "foo!",
263+
},
264+
}
265+
266+
for _, tc := range testCases {
267+
t.Run(tc.name, func(t *testing.T) {
268+
err := tc.schema.VisitJSON(tc.value, tc.options...)
269+
var schemaError = &SchemaError{}
270+
require.Error(t, err)
271+
require.ErrorAs(t, err, &schemaError)
272+
require.NotZero(t, schemaError.Reason)
273+
require.NotContains(t, schemaError.Reason, fmt.Sprint(tc.value))
274+
for _, extra := range tc.extraNotContains {
275+
require.NotContains(t, schemaError.Reason, fmt.Sprint(extra))
276+
}
277+
})
278+
}
279+
}

0 commit comments

Comments
 (0)