1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package validate
16
17 import (
18 "encoding/json"
19 "fmt"
20 "log"
21 "os"
22 "path/filepath"
23 "testing"
24
25 "github.com/go-openapi/errors"
26 "github.com/go-openapi/spec"
27 "github.com/go-openapi/strfmt"
28 "github.com/stretchr/testify/assert"
29 "github.com/stretchr/testify/require"
30 )
31
32 var (
33
34 PetStore20 string
35
36
37 PetStoreJSONMessage json.RawMessage
38 )
39
40 func init() {
41 petstoreFixture := filepath.Join("fixtures", "petstore", "swagger.json")
42 petstore, err := os.ReadFile(petstoreFixture)
43 if err != nil {
44 log.Fatalf("could not initialize fixture: %s: %v", petstoreFixture, err)
45 }
46 PetStoreJSONMessage = json.RawMessage(petstore)
47 PetStore20 = string(petstore)
48 }
49
50 func stringItems() *spec.Items {
51 return spec.NewItems().Typed(stringType, "")
52 }
53
54 func requiredError(param *spec.Parameter, data interface{}) *errors.Validation {
55 return errors.Required(param.Name, param.In, data)
56 }
57
58 func maxErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
59 return errors.ExceedsMaximum(path, in, *items.Maximum, items.ExclusiveMaximum, data)
60 }
61
62 func minErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
63 return errors.ExceedsMinimum(path, in, *items.Minimum, items.ExclusiveMinimum, data)
64 }
65
66 func multipleOfErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
67 return errors.NotMultipleOf(path, in, *items.MultipleOf, data)
68 }
69
70
75
76 func maxLengthErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
77 return errors.TooLong(path, in, *items.MaxLength, data)
78 }
79
80 func minLengthErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
81 return errors.TooShort(path, in, *items.MinLength, data)
82 }
83
84 func patternFailItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
85 return errors.FailedPattern(path, in, items.Pattern, data)
86 }
87
88 func enumFailItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
89 return errors.EnumFail(path, in, data, items.Enum)
90 }
91
92 func minItemsErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
93 return errors.TooFewItems(path, in, *items.MinItems, data)
94 }
95
96 func maxItemsErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
97 return errors.TooManyItems(path, in, *items.MaxItems, data)
98 }
99
100 func duplicatesErrorItems(path, in string) *errors.Validation {
101 return errors.DuplicateItems(path, in)
102 }
103
104 func TestNumberItemsValidation(t *testing.T) {
105
106 values := [][]interface{}{
107 {23, 49, 56, 21, 14, 35, 28, 7, 42},
108 {uint(23), uint(49), uint(56), uint(21), uint(14), uint(35), uint(28), uint(7), uint(42)},
109 {float64(23), float64(49), float64(56), float64(21), float64(14), float64(35), float64(28), float64(7), float64(42)},
110 }
111
112 for i, v := range values {
113 items := spec.NewItems()
114 items.WithMaximum(makeFloat(v[1]), false)
115 items.WithMinimum(makeFloat(v[3]), false)
116 items.WithMultipleOf(makeFloat(v[7]))
117 items.WithEnum(v[3], v[6], v[8], v[1])
118 items.Typed("integer", "int32")
119 parent := spec.QueryParam("factors").CollectionOf(items, "")
120 path := fmt.Sprintf("factors.%d", i)
121 validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
122
123
124 err := validator.Validate(i, v[0])
125 assert.True(t, err.HasErrors())
126 require.NotEmpty(t, err.Errors)
127 require.EqualError(t, multipleOfErrorItems(path, validator.in, items, v[0]), err.Errors[0].Error())
128
129
130 err = validator.Validate(i, v[1])
131 assert.True(t, err == nil || err.IsValid())
132 err = validator.Validate(i, v[2])
133 assert.True(t, err.HasErrors())
134 require.NotEmpty(t, err.Errors)
135 require.EqualError(t, maxErrorItems(path, validator.in, items, v[2]), err.Errors[0].Error())
136
137
138 items.ExclusiveMaximum = true
139
140 validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
141 err = validator.Validate(i, v[1])
142 assert.True(t, err.HasErrors())
143 require.NotEmpty(t, err.Errors)
144 require.EqualError(t, maxErrorItems(path, validator.in, items, v[1]), err.Errors[0].Error())
145
146
147 err = validator.Validate(i, v[3])
148 assert.True(t, err == nil || err.IsValid())
149 err = validator.Validate(i, v[4])
150 assert.True(t, err.HasErrors())
151 require.NotEmpty(t, err.Errors)
152 require.EqualError(t, minErrorItems(path, validator.in, items, v[4]), err.Errors[0].Error())
153
154
155 items.ExclusiveMinimum = true
156
157 validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
158 err = validator.Validate(i, v[3])
159 assert.True(t, err.HasErrors())
160 require.NotEmpty(t, err.Errors)
161 require.EqualError(t, minErrorItems(path, validator.in, items, v[3]), err.Errors[0].Error())
162
163
164 err = validator.Validate(i, v[5])
165 assert.True(t, err.HasErrors())
166 require.NotEmpty(t, err.Errors)
167 require.EqualError(t, enumFailItems(path, validator.in, items, v[5]), err.Errors[0].Error())
168
169
170 err = validator.Validate(i, v[6])
171 assert.True(t, err == nil || err.IsValid())
172 }
173
174 }
175
176 func TestStringItemsValidation(t *testing.T) {
177 items := spec.NewItems().WithMinLength(3).WithMaxLength(5).WithPattern(`^[a-z]+$`).Typed(stringType, "")
178 items.WithEnum("aaa", "bbb", "ccc")
179 parent := spec.QueryParam("tags").CollectionOf(items, "")
180 path := parent.Name + ".1"
181 validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
182
183
184 data := ""
185 err := validator.Validate(1, data)
186 assert.True(t, err.HasErrors())
187 require.NotEmpty(t, err.Errors)
188 require.EqualError(t, minLengthErrorItems(path, validator.in, items, data), err.Errors[0].Error())
189
190
191 data = "abcdef"
192 err = validator.Validate(1, data)
193 assert.True(t, err.HasErrors())
194 require.NotEmpty(t, err.Errors)
195 require.EqualError(t, maxLengthErrorItems(path, validator.in, items, data), err.Errors[0].Error())
196
197
198 data = "a"
199 err = validator.Validate(1, data)
200 assert.True(t, err.HasErrors())
201 require.NotEmpty(t, err.Errors)
202 require.EqualError(t, minLengthErrorItems(path, validator.in, items, data), err.Errors[0].Error())
203
204
205 data = "a394"
206 err = validator.Validate(1, data)
207 assert.True(t, err.HasErrors())
208 require.NotEmpty(t, err.Errors)
209 require.EqualError(t, patternFailItems(path, validator.in, items, data), err.Errors[0].Error())
210
211
212 data = "abcde"
213 err = validator.Validate(1, data)
214 assert.True(t, err.HasErrors())
215 require.NotEmpty(t, err.Errors)
216 require.EqualError(t, enumFailItems(path, validator.in, items, data), err.Errors[0].Error())
217
218
219 err = validator.Validate(1, "bbb")
220 assert.True(t, err == nil || err.IsValid())
221 }
222
223 func TestArrayItemsValidation(t *testing.T) {
224 items := spec.NewItems().CollectionOf(stringItems(), "").WithMinItems(1).WithMaxItems(5).UniqueValues()
225 items.WithEnum("aaa", "bbb", "ccc")
226 parent := spec.QueryParam("tags").CollectionOf(items, "")
227 path := parent.Name + ".1"
228 validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
229
230
231 data := []string{}
232 err := validator.Validate(1, data)
233 assert.True(t, err.HasErrors())
234 require.NotEmpty(t, err.Errors)
235 require.EqualError(t, minItemsErrorItems(path, validator.in, items, len(data)), err.Errors[0].Error())
236
237 data = []string{"a", "b", "c", "d", "e", "f"}
238 err = validator.Validate(1, data)
239 assert.True(t, err.HasErrors())
240 require.NotEmpty(t, err.Errors)
241 require.EqualError(t, maxItemsErrorItems(path, validator.in, items, len(data)), err.Errors[0].Error())
242
243 err = validator.Validate(1, []string{"a", "a"})
244 assert.True(t, err.HasErrors())
245 require.NotEmpty(t, err.Errors)
246 require.EqualError(t, duplicatesErrorItems(path, validator.in), err.Errors[0].Error())
247
248
249 data = []string{"a", "b", "c"}
250 err = validator.Validate(1, data)
251 assert.True(t, err.HasErrors())
252 require.NotEmpty(t, err.Errors)
253 require.EqualError(t, enumFailItems(path, validator.in, items, data), err.Errors[0].Error())
254
255
256 strItems := spec.NewItems().WithMinLength(3).WithMaxLength(5).WithPattern(`^[a-z]+$`).Typed(stringType, "")
257 items = spec.NewItems().CollectionOf(strItems, "").WithMinItems(1).WithMaxItems(5).UniqueValues()
258 validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
259
260 data = []string{"aa", "bbb", "ccc"}
261 err = validator.Validate(1, data)
262 assert.True(t, err.HasErrors())
263 require.NotEmpty(t, err.Errors)
264 require.EqualError(t, minLengthErrorItems(path+".0", parent.In, strItems, data[0]), err.Errors[0].Error())
265 }
266
View as plain text