1package validation
2
3// Copyright 2017 Microsoft Corporation
4//
5//  Licensed under the Apache License, Version 2.0 (the "License");
6//  you may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at
8//
9//      http://www.apache.org/licenses/LICENSE-2.0
10//
11//  Unless required by applicable law or agreed to in writing, software
12//  distributed under the License is distributed on an "AS IS" BASIS,
13//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14//  See the License for the specific language governing permissions and
15//  limitations under the License.
16
17import (
18	"fmt"
19	"reflect"
20	"strings"
21	"testing"
22
23	"github.com/stretchr/testify/require"
24)
25
26func TestCheckForUniqueInArrayTrue(t *testing.T) {
27	require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{1, 2, 3})), true)
28}
29
30func TestCheckForUniqueInArrayFalse(t *testing.T) {
31	require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{1, 2, 3, 3})), false)
32}
33
34func TestCheckForUniqueInArrayEmpty(t *testing.T) {
35	require.Equal(t, checkForUniqueInArray(reflect.ValueOf([]int{})), false)
36}
37
38func TestCheckForUniqueInMapTrue(t *testing.T) {
39	require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[string]int{"one": 1, "two": 2})), true)
40}
41
42func TestCheckForUniqueInMapFalse(t *testing.T) {
43	require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[int]string{1: "one", 2: "one"})), false)
44}
45
46func TestCheckForUniqueInMapEmpty(t *testing.T) {
47	require.Equal(t, checkForUniqueInMap(reflect.ValueOf(map[int]string{})), false)
48}
49
50func TestCheckEmpty_WithValueEmptyRuleTrue(t *testing.T) {
51	var x interface{}
52	v := Constraint{
53		Target: "str",
54		Name:   Empty,
55		Rule:   true,
56		Chain:  nil,
57	}
58	expected := createError(reflect.ValueOf(x), v, "value can not be null or empty; required parameter")
59	require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error())
60}
61
62func TestCheckEmpty_WithEmptyStringRuleFalse(t *testing.T) {
63	var x interface{}
64	v := Constraint{
65		Target: "str",
66		Name:   Empty,
67		Rule:   false,
68		Chain:  nil,
69	}
70	require.Nil(t, checkEmpty(reflect.ValueOf(x), v))
71}
72
73func TestCheckEmpty_IncorrectRule(t *testing.T) {
74	var x interface{}
75	v := Constraint{
76		Target: "str",
77		Name:   Empty,
78		Rule:   10,
79		Chain:  nil,
80	}
81	expected := createError(reflect.ValueOf(x), v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule))
82	require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error())
83}
84
85func TestCheckEmpty_WithErrorArray(t *testing.T) {
86	var x interface{} = []string{}
87	v := Constraint{
88		Target: "str",
89		Name:   Empty,
90		Rule:   true,
91		Chain:  nil,
92	}
93	expected := createError(reflect.ValueOf(x), v, "value can not be null or empty; required parameter")
94	require.Equal(t, checkEmpty(reflect.ValueOf(x), v).Error(), expected.Error())
95}
96
97func TestCheckNil_WithNilValueRuleTrue(t *testing.T) {
98	var x interface{}
99	v := Constraint{
100		Target: "x",
101		Name:   Null,
102		Rule:   true,
103		Chain: []Constraint{
104			{"x", MaxItems, 4, nil},
105		},
106	}
107	expected := createError(reflect.ValueOf(x), v, "value can not be null; required parameter")
108	require.Equal(t, checkNil(reflect.ValueOf(x), v).Error(), expected.Error())
109}
110
111func TestCheckNil_WithNilValueRuleFalse(t *testing.T) {
112	var x interface{}
113	v := Constraint{
114		Target: "x",
115		Name:   Null,
116		Rule:   false,
117		Chain: []Constraint{
118			{"x", MaxItems, 4, nil},
119		},
120	}
121	require.Nil(t, checkNil(reflect.ValueOf(x), v))
122}
123
124func TestCheckNil_IncorrectRule(t *testing.T) {
125	var x interface{}
126	c := Constraint{
127		Target: "str",
128		Name:   Null,
129		Rule:   10,
130		Chain:  nil,
131	}
132	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", c.Name, c.Rule))
133	require.Equal(t, checkNil(reflect.ValueOf(x), c).Error(), expected.Error())
134}
135
136func TestValidateArrayMap_WithNilValueRuleTrue(t *testing.T) {
137	var a []string
138	var x interface{} = a
139	c := Constraint{
140		Target: "arr",
141		Name:   Null,
142		Rule:   true,
143		Chain:  nil,
144	}
145	expected := createError(reflect.ValueOf(x), c, "value can not be null; required parameter")
146	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c), expected)
147}
148
149func TestValidateArrayMap_WithNilValueRuleFalse(t *testing.T) {
150	var x interface{} = []string{}
151	c := Constraint{
152		Target: "arr",
153		Name:   Null,
154		Rule:   false,
155		Chain:  nil,
156	}
157	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
158}
159
160func TestValidateArrayMap_WithValueRuleNullTrue(t *testing.T) {
161	var x interface{} = []string{"1", "2"}
162	c := Constraint{
163		Target: "arr",
164		Name:   Null,
165		Rule:   false,
166		Chain:  nil,
167	}
168	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
169}
170
171func TestValidateArrayMap_WithEmptyValueRuleTrue(t *testing.T) {
172	var x interface{} = []string{}
173	c := Constraint{
174		Target: "arr",
175		Name:   Empty,
176		Rule:   true,
177		Chain:  nil,
178	}
179	expected := createError(reflect.ValueOf(x), c, "value can not be null or empty; required parameter")
180	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c), expected)
181}
182
183func TestValidateArrayMap_WithEmptyValueRuleFalse(t *testing.T) {
184	var x interface{} = []string{}
185	c := Constraint{
186		Target: "arr",
187		Name:   Empty,
188		Rule:   false,
189		Chain:  nil,
190	}
191	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
192}
193
194func TestValidateArrayMap_WithEmptyRuleEmptyTrue(t *testing.T) {
195	var x interface{} = []string{"1", "2"}
196	c := Constraint{
197		Target: "arr",
198		Name:   Empty,
199		Rule:   false,
200		Chain:  nil,
201	}
202	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
203}
204
205func TestValidateArrayMap_MaxItemsIncorrectRule(t *testing.T) {
206	var x interface{} = []string{"1", "2"}
207	c := Constraint{
208		Target: "arr",
209		Name:   MaxItems,
210		Rule:   false,
211		Chain:  nil,
212	}
213	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule))
214	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
215}
216
217func TestValidateArrayMap_MaxItemsNoError(t *testing.T) {
218	var x interface{} = []string{"1", "2"}
219	c := Constraint{
220		Target: "arr",
221		Name:   MaxItems,
222		Rule:   2,
223		Chain:  nil,
224	}
225	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
226}
227
228func TestValidateArrayMap_MaxItemsWithError(t *testing.T) {
229	var x interface{} = []string{"1", "2", "3"}
230	c := Constraint{
231		Target: "arr",
232		Name:   MaxItems,
233		Rule:   2,
234		Chain:  nil,
235	}
236	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("maximum item limit is %v; got: 3", c.Rule))
237	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
238}
239
240func TestValidateArrayMap_MaxItemsWithEmpty(t *testing.T) {
241	var x interface{} = []string{}
242	c := Constraint{
243		Target: "arr",
244		Name:   MaxItems,
245		Rule:   2,
246		Chain:  nil,
247	}
248	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
249}
250
251func TestValidateArrayMap_MinItemsIncorrectRule(t *testing.T) {
252	var x interface{} = []int{1, 2}
253	c := Constraint{
254		Target: "arr",
255		Name:   MinItems,
256		Rule:   false,
257		Chain:  nil,
258	}
259	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule))
260	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
261}
262
263func TestValidateArrayMap_MinItemsNoError1(t *testing.T) {
264	c := Constraint{
265		Target: "arr",
266		Name:   MinItems,
267		Rule:   2,
268		Chain:  nil,
269	}
270	require.Nil(t, validateArrayMap(reflect.ValueOf([]int{1, 2}), c))
271}
272
273func TestValidateArrayMap_MinItemsNoError2(t *testing.T) {
274	c := Constraint{
275		Target: "arr",
276		Name:   MinItems,
277		Rule:   2,
278		Chain:  nil,
279	}
280	require.Nil(t, validateArrayMap(reflect.ValueOf([]int{1, 2, 3}), c))
281}
282
283func TestValidateArrayMap_MinItemsWithError(t *testing.T) {
284	var x interface{} = []int{1}
285	c := Constraint{
286		Target: "arr",
287		Name:   MinItems,
288		Rule:   2,
289		Chain:  nil,
290	}
291	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: 1", c.Rule))
292	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
293}
294
295func TestValidateArrayMap_MinItemsWithEmpty(t *testing.T) {
296	var x interface{} = []int{}
297	c := Constraint{
298		Target: "arr",
299		Name:   MinItems,
300		Rule:   2,
301		Chain:  nil,
302	}
303	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: 0", c.Rule))
304	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
305}
306
307func TestValidateArrayMap_Map_MaxItemsIncorrectRule(t *testing.T) {
308	var x interface{} = map[int]string{1: "1", 2: "2"}
309	c := Constraint{
310		Target: "arr",
311		Name:   MaxItems,
312		Rule:   false,
313		Chain:  nil,
314	}
315	require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(),
316		fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)), true)
317}
318
319func TestValidateArrayMap_Map_MaxItemsNoError(t *testing.T) {
320	var x interface{} = map[int]string{1: "1", 2: "2"}
321	c := Constraint{
322		Target: "arr",
323		Name:   MaxItems,
324		Rule:   2,
325		Chain:  nil,
326	}
327	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
328}
329
330func TestValidateArrayMap_Map_MaxItemsWithError(t *testing.T) {
331	a := map[int]string{1: "1", 2: "2", 3: "3"}
332	var x interface{} = a
333	c := Constraint{
334		Target: "arr",
335		Name:   MaxItems,
336		Rule:   2,
337		Chain:  nil,
338	}
339	require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(),
340		fmt.Sprintf("maximum item limit is %v; got: %v", c.Rule, len(a))), true)
341}
342
343func TestValidateArrayMap_Map_MaxItemsWithEmpty(t *testing.T) {
344	a := map[int]string{}
345	var x interface{} = a
346	c := Constraint{
347		Target: "arr",
348		Name:   MaxItems,
349		Rule:   2,
350		Chain:  nil,
351	}
352	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
353}
354
355func TestValidateArrayMap_Map_MinItemsIncorrectRule(t *testing.T) {
356	var x interface{} = map[int]string{1: "1", 2: "2"}
357	c := Constraint{
358		Target: "arr",
359		Name:   MinItems,
360		Rule:   false,
361		Chain:  nil,
362	}
363	require.Equal(t, strings.Contains(validateArrayMap(reflect.ValueOf(x), c).Error(),
364		fmt.Sprintf("rule must be integer for %v constraint; got: %v", c.Name, c.Rule)), true)
365}
366
367func TestValidateArrayMap_Map_MinItemsNoError1(t *testing.T) {
368	var x interface{} = map[int]string{1: "1", 2: "2"}
369	require.Nil(t, validateArrayMap(reflect.ValueOf(x),
370		Constraint{
371			Target: "arr",
372			Name:   MinItems,
373			Rule:   2,
374			Chain:  nil,
375		}))
376}
377
378func TestValidateArrayMap_Map_MinItemsNoError2(t *testing.T) {
379	var x interface{} = map[int]string{1: "1", 2: "2", 3: "3"}
380	c := Constraint{
381		Target: "arr",
382		Name:   MinItems,
383		Rule:   2,
384		Chain:  nil,
385	}
386	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
387}
388
389func TestValidateArrayMap_Map_MinItemsWithError(t *testing.T) {
390	a := map[int]string{1: "1"}
391	var x interface{} = a
392	c := Constraint{
393		Target: "arr",
394		Name:   MinItems,
395		Rule:   2,
396		Chain:  nil,
397	}
398	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: %v", c.Rule, len(a)))
399	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
400}
401
402func TestValidateArrayMap_Map_MinItemsWithEmpty(t *testing.T) {
403	a := map[int]string{}
404	var x interface{} = a
405	c := Constraint{
406		Target: "arr",
407		Name:   MinItems,
408		Rule:   2,
409		Chain:  nil,
410	}
411	expected := createError(reflect.ValueOf(x), c, fmt.Sprintf("minimum item limit is %v; got: %v", c.Rule, len(a)))
412	require.Equal(t, validateArrayMap(reflect.ValueOf(x), c).Error(), expected.Error())
413}
414
415// func TestValidateArrayMap_Map_MinItemsNil(t *testing.T) {
416// 	var a map[int]float64
417// 	var x interface{} = a
418// 	c := Constraint{
419// 		Target: "str",
420// 		Name:   MinItems,
421// 		Rule:   true,
422// 		Chain:  nil,
423// 	}
424// 	expected := createError(reflect.Value(x), c, fmt.Sprintf("all items in parameter %v must be unique; got:%v", c.Target, x))
425// 	if z := validateArrayMap(reflect.ValueOf(x), c); strings.Contains(z.Error(), "all items in parameter str must be unique;") {
426// 		t.Fatalf("autorest/validation: valiateArrayMap failed to return error \nexpect: %v;\ngot: %v", expected, z)
427// 	}
428// }
429
430func TestValidateArrayMap_Map_UniqueItemsTrue(t *testing.T) {
431	var x interface{} = map[float64]int{1.2: 1, 1.4: 2}
432	c := Constraint{
433		Target: "str",
434		Name:   UniqueItems,
435		Rule:   true,
436		Chain:  nil,
437	}
438	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
439}
440
441func TestValidateArrayMap_Map_UniqueItemsFalse(t *testing.T) {
442	var x interface{} = map[string]string{"1": "1", "2": "2", "3": "1"}
443	c := Constraint{
444		Target: "str",
445		Name:   UniqueItems,
446		Rule:   true,
447		Chain:  nil,
448	}
449	z := validateArrayMap(reflect.ValueOf(x), c)
450	require.Equal(t, strings.Contains(z.Error(),
451		fmt.Sprintf("all items in parameter %q must be unique", c.Target)), true)
452}
453
454func TestValidateArrayMap_Map_UniqueItemsEmpty(t *testing.T) {
455	// Consider Empty map as not unique returns false
456	var x interface{} = map[int]float64{}
457	c := Constraint{
458		Target: "str",
459		Name:   UniqueItems,
460		Rule:   true,
461		Chain:  nil,
462	}
463	z := validateArrayMap(reflect.ValueOf(x), c)
464	require.Equal(t, strings.Contains(z.Error(),
465		fmt.Sprintf("all items in parameter %q must be unique", c.Target)), true)
466}
467
468func TestValidateArrayMap_Map_UniqueItemsNil(t *testing.T) {
469	var a map[int]float64
470	var x interface{} = a
471	c := Constraint{
472		Target: "str",
473		Name:   UniqueItems,
474		Rule:   true,
475		Chain:  nil,
476	}
477	z := validateArrayMap(reflect.ValueOf(x), c)
478	require.Equal(t, strings.Contains(z.Error(),
479		fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true)
480}
481
482func TestValidateArrayMap_Array_UniqueItemsTrue(t *testing.T) {
483	var x interface{} = []int{1, 2}
484	c := Constraint{
485		Target: "str",
486		Name:   UniqueItems,
487		Rule:   true,
488		Chain:  nil,
489	}
490	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
491}
492
493func TestValidateArrayMap_Array_UniqueItemsFalse(t *testing.T) {
494	var x interface{} = []string{"1", "2", "1"}
495	c := Constraint{
496		Target: "str",
497		Name:   UniqueItems,
498		Rule:   true,
499		Chain:  nil,
500	}
501	z := validateArrayMap(reflect.ValueOf(x), c)
502	require.Equal(t, strings.Contains(z.Error(),
503		fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true)
504}
505
506func TestValidateArrayMap_Array_UniqueItemsEmpty(t *testing.T) {
507	// Consider Empty array as not unique returns false
508	var x interface{} = []float64{}
509	c := Constraint{
510		Target: "str",
511		Name:   UniqueItems,
512		Rule:   true,
513		Chain:  nil,
514	}
515	z := validateArrayMap(reflect.ValueOf(x), c)
516	require.Equal(t, strings.Contains(z.Error(),
517		fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true)
518}
519
520func TestValidateArrayMap_Array_UniqueItemsNil(t *testing.T) {
521	// Consider nil array as not unique returns false
522	var a []float64
523	var x interface{} = a
524	c := Constraint{
525		Target: "str",
526		Name:   UniqueItems,
527		Rule:   true,
528		Chain:  nil,
529	}
530	z := validateArrayMap(reflect.ValueOf(x), c)
531	require.Equal(t, strings.Contains(z.Error(),
532		fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, x)), true)
533}
534
535func TestValidateArrayMap_Array_UniqueItemsInvalidType(t *testing.T) {
536	var x interface{} = "hello"
537	c := Constraint{
538		Target: "str",
539		Name:   UniqueItems,
540		Rule:   true,
541		Chain:  nil,
542	}
543	z := validateArrayMap(reflect.ValueOf(x), c)
544	require.Equal(t, strings.Contains(z.Error(),
545		fmt.Sprintf("type must be array, slice or map for constraint %v; got: %v", c.Name, reflect.ValueOf(x).Kind())), true)
546}
547
548func TestValidateArrayMap_Array_UniqueItemsInvalidConstraint(t *testing.T) {
549	var x interface{} = "hello"
550	c := Constraint{
551		Target: "str",
552		Name:   "sdad",
553		Rule:   true,
554		Chain:  nil,
555	}
556	z := validateArrayMap(reflect.ValueOf(x), c)
557	require.Equal(t, strings.Contains(z.Error(),
558		fmt.Sprintf("constraint %v is not applicable to array, slice and map type", c.Name)), true)
559}
560
561func TestValidateArrayMap_ValidateChainConstraint1(t *testing.T) {
562	a := []int{1, 2, 3, 4}
563	var x interface{} = a
564	c := Constraint{
565		Target: "str",
566		Name:   Null,
567		Rule:   true,
568		Chain: []Constraint{
569			{"str", MaxItems, 3, nil},
570		},
571	}
572	z := validateArrayMap(reflect.ValueOf(x), c)
573	require.Equal(t, strings.Contains(z.Error(),
574		fmt.Sprintf("maximum item limit is %v; got: %v", (c.Chain)[0].Rule, len(a))), true)
575}
576
577func TestValidateArrayMap_ValidateChainConstraint2(t *testing.T) {
578	a := []int{1, 2, 3, 4}
579	var x interface{} = a
580	c := Constraint{
581		Target: "str",
582		Name:   Empty,
583		Rule:   true,
584		Chain: []Constraint{
585			{"str", MaxItems, 3, nil},
586		},
587	}
588	z := validateArrayMap(reflect.ValueOf(x), c)
589	require.Equal(t, strings.Contains(z.Error(),
590		fmt.Sprintf("maximum item limit is %v; got: %v", (c.Chain)[0].Rule, len(a))), true)
591}
592
593func TestValidateArrayMap_ValidateChainConstraint3(t *testing.T) {
594	var a []string
595	var x interface{} = a
596	c := Constraint{
597		Target: "str",
598		Name:   Null,
599		Rule:   true,
600		Chain: []Constraint{
601			{"str", MaxItems, 3, nil},
602		},
603	}
604	z := validateArrayMap(reflect.ValueOf(x), c)
605	require.Equal(t, strings.Contains(z.Error(),
606		fmt.Sprintf("value can not be null; required parameter")), true)
607}
608
609func TestValidateArrayMap_ValidateChainConstraint4(t *testing.T) {
610	var x interface{} = []int{}
611	c := Constraint{
612		Target: "str",
613		Name:   Empty,
614		Rule:   true,
615		Chain: []Constraint{
616			{"str", MaxItems, 3, nil},
617		},
618	}
619	z := validateArrayMap(reflect.ValueOf(x), c)
620	require.Equal(t, strings.Contains(z.Error(),
621		fmt.Sprintf("value can not be null or empty; required parameter")), true)
622}
623
624func TestValidateArrayMap_ValidateChainConstraintNilNotRequired(t *testing.T) {
625	var a []int
626	var x interface{} = a
627	c := Constraint{
628		Target: "str",
629		Name:   Null,
630		Rule:   false,
631		Chain: []Constraint{
632			{"str", MaxItems, 3, nil},
633		},
634	}
635	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
636}
637
638func TestValidateArrayMap_ValidateChainConstraintEmptyNotRequired(t *testing.T) {
639	var x interface{} = map[string]int{}
640	c := Constraint{
641		Target: "str",
642		Name:   Empty,
643		Rule:   false,
644		Chain: []Constraint{
645			{"str", MaxItems, 3, nil},
646		},
647	}
648	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
649}
650
651func TestValidateArrayMap_ReadOnlyWithError(t *testing.T) {
652	var x interface{} = []int{1, 2}
653	c := Constraint{
654		Target: "str",
655		Name:   ReadOnly,
656		Rule:   true,
657		Chain: []Constraint{
658			{"str", MaxItems, 3, nil},
659		},
660	}
661	z := validateArrayMap(reflect.ValueOf(x), c)
662	require.Equal(t, strings.Contains(z.Error(),
663		fmt.Sprintf("readonly parameter; must send as nil or empty in request")), true)
664}
665
666func TestValidateArrayMap_ReadOnlyWithoutError(t *testing.T) {
667	var x interface{} = []int{}
668	c := Constraint{
669		Target: "str",
670		Name:   ReadOnly,
671		Rule:   true,
672		Chain:  nil,
673	}
674	require.Nil(t, validateArrayMap(reflect.ValueOf(x), c))
675}
676
677func TestValidateString_ReadOnly(t *testing.T) {
678	var x interface{} = "Hello Gopher"
679	c := Constraint{
680		Target: "str",
681		Name:   ReadOnly,
682		Rule:   true,
683		Chain:  nil,
684	}
685	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
686		fmt.Sprintf("readonly parameter; must send as nil or empty in request")), true)
687}
688
689func TestValidateString_EmptyTrue(t *testing.T) {
690	// Empty true means parameter is required but Empty returns error
691	c := Constraint{
692		Target: "str",
693		Name:   Empty,
694		Rule:   true,
695		Chain:  nil,
696	}
697	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(""), c).Error(),
698		fmt.Sprintf("value can not be null or empty; required parameter")), true)
699}
700
701func TestValidateString_EmptyFalse(t *testing.T) {
702	// Empty false means parameter is not required and Empty return nil
703	var x interface{}
704	c := Constraint{
705		Target: "str",
706		Name:   Empty,
707		Rule:   false,
708		Chain:  nil,
709	}
710	require.Nil(t, validateString(reflect.ValueOf(x), c))
711}
712
713func TestValidateString_MaxLengthInvalid(t *testing.T) {
714	// Empty true means parameter is required but Empty returns error
715	var x interface{} = "Hello"
716	c := Constraint{
717		Target: "str",
718		Name:   MaxLength,
719		Rule:   4,
720		Chain:  nil,
721	}
722	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
723		fmt.Sprintf("value length must be less than or equal to %v", c.Rule)), true)
724}
725
726func TestValidateString_MaxLengthValid(t *testing.T) {
727	// Empty false means parameter is not required and Empty return nil
728	c := Constraint{
729		Target: "str",
730		Name:   MaxLength,
731		Rule:   7,
732		Chain:  nil,
733	}
734	require.Nil(t, validateString(reflect.ValueOf("Hello"), c))
735}
736
737func TestValidateString_MaxLengthRuleInvalid(t *testing.T) {
738	var x interface{} = "Hello"
739	c := Constraint{
740		Target: "str",
741		Name:   MaxLength,
742		Rule:   true, // must be int for maxLength
743		Chain:  nil,
744	}
745	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
746		fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true)
747}
748
749func TestValidateString_MinLengthInvalid(t *testing.T) {
750	var x interface{} = "Hello"
751	c := Constraint{
752		Target: "str",
753		Name:   MinLength,
754		Rule:   10,
755		Chain:  nil,
756	}
757	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
758		fmt.Sprintf("value length must be greater than or equal to %v", c.Rule)), true)
759}
760
761func TestValidateString_MinLengthValid(t *testing.T) {
762	c := Constraint{
763		Target: "str",
764		Name:   MinLength,
765		Rule:   2,
766		Chain:  nil,
767	}
768	require.Nil(t, validateString(reflect.ValueOf("Hello"), c))
769}
770
771func TestValidateString_MinLengthRuleInvalid(t *testing.T) {
772	var x interface{} = "Hello"
773	c := Constraint{
774		Target: "str",
775		Name:   MinLength,
776		Rule:   true, // must be int for minLength
777		Chain:  nil,
778	}
779	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
780		fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true)
781}
782
783func TestValidateString_PatternInvalidPattern(t *testing.T) {
784	var x interface{} = "Hello"
785	c := Constraint{
786		Target: "str",
787		Name:   Pattern,
788		Rule:   `^[[:alnum:$`,
789		Chain:  nil,
790	}
791	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
792		"error parsing regexp: missing closing ]"), true)
793}
794
795func TestValidateString_PatternMatch1(t *testing.T) {
796	c := Constraint{
797		Target: "str",
798		Name:   Pattern,
799		Rule:   `^http://\w+$`,
800		Chain:  nil,
801	}
802	require.Nil(t, validateString(reflect.ValueOf("http://masd"), c))
803}
804
805func TestValidateString_PatternMatch2(t *testing.T) {
806	c := Constraint{
807		Target: "str",
808		Name:   Pattern,
809		Rule:   `^[a-zA-Z0-9]+$`,
810		Chain:  nil,
811	}
812	require.Nil(t, validateString(reflect.ValueOf("asdadad2323sad"), c))
813}
814
815func TestValidateString_PatternNotMatch(t *testing.T) {
816	var x interface{} = "asdad@@ad2323sad"
817	c := Constraint{
818		Target: "str",
819		Name:   Pattern,
820		Rule:   `^[a-zA-Z0-9]+$`,
821		Chain:  nil,
822	}
823	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
824		fmt.Sprintf("value doesn't match pattern %v", c.Rule)), true)
825}
826
827func TestValidateString_InvalidConstraint(t *testing.T) {
828	var x interface{} = "asdad@@ad2323sad"
829	c := Constraint{
830		Target: "str",
831		Name:   UniqueItems,
832		Rule:   "^[a-zA-Z0-9]+$",
833		Chain:  nil,
834	}
835	require.Equal(t, strings.Contains(validateString(reflect.ValueOf(x), c).Error(),
836		fmt.Sprintf("constraint %s is not applicable to string type", c.Name)), true)
837}
838
839func TestValidateFloat_InvalidConstraint(t *testing.T) {
840	var x interface{} = 1.4
841	c := Constraint{
842		Target: "str",
843		Name:   UniqueItems,
844		Rule:   3.0,
845		Chain:  nil,
846	}
847	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
848		fmt.Sprintf("constraint %v is not applicable for type float", c.Name)), true)
849}
850
851func TestValidateFloat_InvalidRuleValue(t *testing.T) {
852	var x interface{} = 1.4
853	c := Constraint{
854		Target: "str",
855		Name:   ExclusiveMinimum,
856		Rule:   3,
857		Chain:  nil,
858	}
859	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
860		fmt.Sprintf("rule must be float value for %v constraint; got: %v", c.Name, c.Rule)), true)
861}
862
863func TestValidateFloat_ExclusiveMinimumConstraintValid(t *testing.T) {
864	c := Constraint{
865		Target: "str",
866		Name:   ExclusiveMinimum,
867		Rule:   1.0,
868		Chain:  nil,
869	}
870	require.Nil(t, validateFloat(reflect.ValueOf(1.42), c))
871}
872
873func TestValidateFloat_ExclusiveMinimumConstraintInvalid(t *testing.T) {
874	var x interface{} = 1.4
875	c := Constraint{
876		Target: "str",
877		Name:   ExclusiveMinimum,
878		Rule:   1.5,
879		Chain:  nil,
880	}
881	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
882		fmt.Sprintf("value must be greater than %v", c.Rule)), true)
883}
884
885func TestValidateFloat_ExclusiveMinimumConstraintBoundary(t *testing.T) {
886	var x interface{} = 1.42
887	c := Constraint{
888		Target: "str",
889		Name:   ExclusiveMinimum,
890		Rule:   1.42,
891		Chain:  nil,
892	}
893	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
894		fmt.Sprintf("value must be greater than %v", c.Rule)), true)
895}
896
897func TestValidateFloat_exclusiveMaximumConstraintValid(t *testing.T) {
898	c := Constraint{
899		Target: "str",
900		Name:   ExclusiveMaximum,
901		Rule:   2.0,
902		Chain:  nil,
903	}
904	require.Nil(t, validateFloat(reflect.ValueOf(1.42), c))
905}
906
907func TestValidateFloat_exclusiveMaximumConstraintInvalid(t *testing.T) {
908	var x interface{} = 1.42
909	c := Constraint{
910		Target: "str",
911		Name:   ExclusiveMaximum,
912		Rule:   1.2,
913		Chain:  nil,
914	}
915	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
916		fmt.Sprintf("value must be less than %v", c.Rule)), true)
917}
918
919func TestValidateFloat_exclusiveMaximumConstraintBoundary(t *testing.T) {
920	var x interface{} = 1.42
921	c := Constraint{
922		Target: "str",
923		Name:   ExclusiveMaximum,
924		Rule:   1.42,
925		Chain:  nil,
926	}
927	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
928		fmt.Sprintf("value must be less than %v", c.Rule)), true)
929}
930
931func TestValidateFloat_inclusiveMaximumConstraintValid(t *testing.T) {
932	c := Constraint{
933		Target: "str",
934		Name:   InclusiveMaximum,
935		Rule:   2.0,
936		Chain:  nil,
937	}
938	require.Nil(t, validateFloat(reflect.ValueOf(1.42), c))
939}
940
941func TestValidateFloat_inclusiveMaximumConstraintInvalid(t *testing.T) {
942	var x interface{} = 1.42
943	c := Constraint{
944		Target: "str",
945		Name:   InclusiveMaximum,
946		Rule:   1.2,
947		Chain:  nil,
948	}
949	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
950		fmt.Sprintf("value must be less than or equal to %v", c.Rule)), true)
951
952}
953
954func TestValidateFloat_inclusiveMaximumConstraintBoundary(t *testing.T) {
955	c := Constraint{
956		Target: "str",
957		Name:   InclusiveMaximum,
958		Rule:   1.42,
959		Chain:  nil,
960	}
961	require.Nil(t, validateFloat(reflect.ValueOf(1.42), c))
962}
963
964func TestValidateFloat_InclusiveMinimumConstraintValid(t *testing.T) {
965	c := Constraint{
966		Target: "str",
967		Name:   InclusiveMinimum,
968		Rule:   1.0,
969		Chain:  nil,
970	}
971	require.Nil(t, validateFloat(reflect.ValueOf(1.42), c))
972}
973
974func TestValidateFloat_InclusiveMinimumConstraintInvalid(t *testing.T) {
975	var x interface{} = 1.42
976	c := Constraint{
977		Target: "str",
978		Name:   InclusiveMinimum,
979		Rule:   1.5,
980		Chain:  nil,
981	}
982	require.Equal(t, strings.Contains(validateFloat(reflect.ValueOf(x), c).Error(),
983		fmt.Sprintf("value must be greater than or equal to %v", c.Rule)), true)
984
985}
986
987func TestValidateFloat_InclusiveMinimumConstraintBoundary(t *testing.T) {
988	c := Constraint{
989		Target: "str",
990		Name:   InclusiveMinimum,
991		Rule:   1.42,
992		Chain:  nil,
993	}
994	require.Nil(t, validateFloat(reflect.ValueOf(1.42), c))
995}
996
997func TestValidateInt_InvalidConstraint(t *testing.T) {
998	var x interface{} = 1
999	c := Constraint{
1000		Target: "str",
1001		Name:   UniqueItems,
1002		Rule:   3,
1003		Chain:  nil,
1004	}
1005	require.Equal(t, strings.Contains(validateInt(reflect.ValueOf(x), c).Error(),
1006		fmt.Sprintf("constraint %s is not applicable for type integer", c.Name)), true)
1007}
1008
1009func TestValidateInt_InvalidRuleValue(t *testing.T) {
1010	var x interface{} = 1
1011	c := Constraint{
1012		Target: "str",
1013		Name:   ExclusiveMinimum,
1014		Rule:   3.4,
1015		Chain:  nil,
1016	}
1017	require.Equal(t, strings.Contains(validateInt(reflect.ValueOf(x), c).Error(),
1018		fmt.Sprintf("rule must be integer value for %v constraint; got: %v", c.Name, c.Rule)), true)
1019}
1020
1021func TestValidateInt_ExclusiveMinimumConstraintValid(t *testing.T) {
1022	c := Constraint{
1023		Target: "str",
1024		Name:   ExclusiveMinimum,
1025		Rule:   1,
1026		Chain:  nil,
1027	}
1028	require.Nil(t, validateInt(reflect.ValueOf(3), c))
1029}
1030
1031func TestValidateInt_ExclusiveMinimumConstraintInvalid(t *testing.T) {
1032	var x interface{} = 1
1033	c := Constraint{
1034		Target: "str",
1035		Name:   ExclusiveMinimum,
1036		Rule:   3,
1037		Chain:  nil,
1038	}
1039	require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(),
1040		createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than %v", c.Rule)).Error())
1041}
1042
1043func TestValidateInt_ExclusiveMinimumConstraintBoundary(t *testing.T) {
1044	var x interface{} = 1
1045	c := Constraint{
1046		Target: "str",
1047		Name:   ExclusiveMinimum,
1048		Rule:   1,
1049		Chain:  nil,
1050	}
1051	require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(),
1052		createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than %v", c.Rule)).Error())
1053}
1054
1055func TestValidateInt_exclusiveMaximumConstraintValid(t *testing.T) {
1056	c := Constraint{
1057		Target: "str",
1058		Name:   ExclusiveMaximum,
1059		Rule:   2,
1060		Chain:  nil,
1061	}
1062	require.Nil(t, validateInt(reflect.ValueOf(1), c))
1063}
1064
1065func TestValidateInt_exclusiveMaximumConstraintInvalid(t *testing.T) {
1066	var x interface{} = 2
1067	c := Constraint{
1068		Target: "str",
1069		Name:   ExclusiveMaximum,
1070		Rule:   1,
1071		Chain:  nil,
1072	}
1073	require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(),
1074		createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than %v", c.Rule)).Error())
1075}
1076
1077func TestValidateInt_exclusiveMaximumConstraintBoundary(t *testing.T) {
1078	var x interface{} = 1
1079	c := Constraint{
1080		Target: "str",
1081		Name:   ExclusiveMaximum,
1082		Rule:   1,
1083		Chain:  nil,
1084	}
1085	require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(),
1086		createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than %v", c.Rule)).Error())
1087}
1088
1089func TestValidateInt_inclusiveMaximumConstraintValid(t *testing.T) {
1090	c := Constraint{
1091		Target: "str",
1092		Name:   InclusiveMaximum,
1093		Rule:   int64(2),
1094		Chain:  nil,
1095	}
1096	require.Nil(t, validateInt(reflect.ValueOf(1), c))
1097}
1098
1099func TestValidateInt_inclusiveMaximumConstraintInvalid(t *testing.T) {
1100	var x interface{} = 2
1101	c := Constraint{
1102		Target: "str",
1103		Name:   InclusiveMaximum,
1104		Rule:   int64(1),
1105		Chain:  nil,
1106	}
1107	require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(),
1108		createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be less than or equal to %v", c.Rule)).Error())
1109}
1110
1111func TestValidateInt_inclusiveMaximumConstraintBoundary(t *testing.T) {
1112	c := Constraint{
1113		Target: "str",
1114		Name:   InclusiveMaximum,
1115		Rule:   int64(1),
1116		Chain:  nil,
1117	}
1118	require.Nil(t, validateInt(reflect.ValueOf(1), c))
1119}
1120
1121func TestValidateInt_InclusiveMinimumConstraintValid(t *testing.T) {
1122	c := Constraint{
1123		Target: "str",
1124		Name:   InclusiveMinimum,
1125		Rule:   1,
1126		Chain:  nil,
1127	}
1128	require.Nil(t, validateInt(reflect.ValueOf(1), c))
1129}
1130
1131func TestValidateInt_InclusiveMinimumConstraintInvalid(t *testing.T) {
1132	var x interface{} = 1
1133	c := Constraint{
1134		Target: "str",
1135		Name:   InclusiveMinimum,
1136		Rule:   2,
1137		Chain:  nil,
1138	}
1139	require.Equal(t, validateInt(reflect.ValueOf(x), c).Error(),
1140		createError(reflect.ValueOf(x), c, fmt.Sprintf("value must be greater than or equal to %v", c.Rule)).Error())
1141}
1142
1143func TestValidateInt_InclusiveMinimumConstraintBoundary(t *testing.T) {
1144	c := Constraint{
1145		Target: "str",
1146		Name:   InclusiveMinimum,
1147		Rule:   1,
1148		Chain:  nil,
1149	}
1150	require.Nil(t, validateInt(reflect.ValueOf(1), c))
1151}
1152
1153func TestValidateInt_MultipleOfWithoutError(t *testing.T) {
1154	c := Constraint{
1155		Target: "str",
1156		Name:   MultipleOf,
1157		Rule:   10,
1158		Chain:  nil,
1159	}
1160	require.Nil(t, validateInt(reflect.ValueOf(2300), c))
1161}
1162
1163func TestValidateInt_MultipleOfWithError(t *testing.T) {
1164	c := Constraint{
1165		Target: "str",
1166		Name:   MultipleOf,
1167		Rule:   11,
1168		Chain:  nil,
1169	}
1170	require.Equal(t, validateInt(reflect.ValueOf(2300), c).Error(),
1171		createError(reflect.ValueOf(2300), c, fmt.Sprintf("value must be a multiple of %v", c.Rule)).Error())
1172}
1173
1174func TestValidatePointer_NilTrue(t *testing.T) {
1175	var z *int
1176	var x interface{} = z
1177	c := Constraint{
1178		Target: "ptr",
1179		Name:   Null,
1180		Rule:   true, // Required property
1181		Chain:  nil,
1182	}
1183	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1184		createError(reflect.ValueOf(x), c, "value can not be null; required parameter").Error())
1185}
1186
1187func TestValidatePointer_NilFalse(t *testing.T) {
1188	var z *int
1189	var x interface{} = z
1190	c := Constraint{
1191		Target: "ptr",
1192		Name:   Null,
1193		Rule:   false, // not required property
1194		Chain:  nil,
1195	}
1196	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1197}
1198
1199func TestValidatePointer_NilReadonlyValid(t *testing.T) {
1200	var z *int
1201	var x interface{} = z
1202	c := Constraint{
1203		Target: "ptr",
1204		Name:   ReadOnly,
1205		Rule:   true,
1206		Chain:  nil,
1207	}
1208	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1209}
1210
1211func TestValidatePointer_NilReadonlyInvalid(t *testing.T) {
1212	z := 10
1213	var x interface{} = &z
1214	c := Constraint{
1215		Target: "ptr",
1216		Name:   ReadOnly,
1217		Rule:   true,
1218		Chain:  nil,
1219	}
1220	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1221		createError(reflect.ValueOf(z), c, "readonly parameter; must send as nil or empty in request").Error())
1222}
1223
1224func TestValidatePointer_IntValid(t *testing.T) {
1225	z := 10
1226	var x interface{} = &z
1227	c := Constraint{
1228		Target: "ptr",
1229		Name:   InclusiveMinimum,
1230		Rule:   3,
1231		Chain:  nil,
1232	}
1233	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1234}
1235
1236func TestValidatePointer_IntInvalid(t *testing.T) {
1237	z := 10
1238	var x interface{} = &z
1239	c := Constraint{
1240		Target: "ptr",
1241		Name:   Null,
1242		Rule:   true,
1243		Chain: []Constraint{
1244			{
1245				Target: "ptr",
1246				Name:   InclusiveMinimum,
1247				Rule:   11,
1248				Chain:  nil,
1249			},
1250		},
1251	}
1252	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1253		createError(reflect.ValueOf(10), c.Chain[0], "value must be greater than or equal to 11").Error())
1254}
1255
1256func TestValidatePointer_IntInvalidConstraint(t *testing.T) {
1257	z := 10
1258	var x interface{} = &z
1259	c := Constraint{
1260		Target: "ptr",
1261		Name:   Null,
1262		Rule:   true,
1263		Chain: []Constraint{
1264			{
1265				Target: "ptr",
1266				Name:   MaxItems,
1267				Rule:   3,
1268				Chain:  nil,
1269			},
1270		},
1271	}
1272	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1273		createError(reflect.ValueOf(10), c.Chain[0],
1274			fmt.Sprintf("constraint %v is not applicable for type integer", MaxItems)).Error())
1275}
1276
1277func TestValidatePointer_ValidInt64(t *testing.T) {
1278	z := int64(10)
1279	var x interface{} = &z
1280	c := Constraint{
1281		Target: "ptr",
1282		Name:   Null,
1283		Rule:   true,
1284		Chain: []Constraint{
1285			{
1286				Target: "ptr",
1287				Name:   InclusiveMinimum,
1288				Rule:   3,
1289				Chain:  nil,
1290			},
1291		}}
1292	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1293}
1294
1295func TestValidatePointer_InvalidConstraintInt64(t *testing.T) {
1296	z := int64(10)
1297	var x interface{} = &z
1298	c := Constraint{
1299		Target: "ptr",
1300		Name:   Null,
1301		Rule:   true,
1302		Chain: []Constraint{
1303			{
1304				Target: "ptr",
1305				Name:   MaxItems,
1306				Rule:   3,
1307				Chain:  nil,
1308			},
1309		},
1310	}
1311	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1312		createError(reflect.ValueOf(10), c.Chain[0],
1313			fmt.Sprintf("constraint %v is not applicable for type integer", MaxItems)).Error())
1314}
1315
1316func TestValidatePointer_ValidFloat(t *testing.T) {
1317	z := 10.1
1318	var x interface{} = &z
1319	c := Constraint{
1320		Target: "ptr",
1321		Name:   Null,
1322		Rule:   true,
1323		Chain: []Constraint{
1324			{
1325				Target: "ptr",
1326				Name:   InclusiveMinimum,
1327				Rule:   3.0,
1328				Chain:  nil,
1329			}}}
1330	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1331}
1332
1333func TestValidatePointer_InvalidFloat(t *testing.T) {
1334	z := 10.1
1335	var x interface{} = &z
1336	c := Constraint{
1337		Target: "ptr",
1338		Name:   Null,
1339		Rule:   true,
1340		Chain: []Constraint{
1341			{
1342				Target: "ptr",
1343				Name:   InclusiveMinimum,
1344				Rule:   12.0,
1345				Chain:  nil,
1346			}},
1347	}
1348	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1349		createError(reflect.ValueOf(10.1), c.Chain[0],
1350			"value must be greater than or equal to 12").Error())
1351}
1352
1353func TestValidatePointer_InvalidConstraintFloat(t *testing.T) {
1354	z := 10.1
1355	var x interface{} = &z
1356	c := Constraint{
1357		Target: "ptr",
1358		Name:   Null,
1359		Rule:   true,
1360		Chain: []Constraint{
1361			{
1362				Target: "ptr",
1363				Name:   MaxItems,
1364				Rule:   3.0,
1365				Chain:  nil,
1366			}},
1367	}
1368	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1369		createError(reflect.ValueOf(10.1), c.Chain[0],
1370			fmt.Sprintf("constraint %v is not applicable for type float", MaxItems)).Error())
1371}
1372
1373func TestValidatePointer_StringValid(t *testing.T) {
1374	z := "hello"
1375	var x interface{} = &z
1376	c := Constraint{
1377		Target: "ptr",
1378		Name:   Null,
1379		Rule:   true,
1380		Chain: []Constraint{
1381			{
1382				Target: "ptr",
1383				Name:   Pattern,
1384				Rule:   "^[a-z]+$",
1385				Chain:  nil,
1386			}}}
1387	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1388}
1389
1390func TestValidatePointer_StringInvalid(t *testing.T) {
1391	z := "hello"
1392	var x interface{} = &z
1393	c := Constraint{
1394		Target: "ptr",
1395		Name:   Null,
1396		Rule:   true,
1397		Chain: []Constraint{
1398			{
1399				Target: "ptr",
1400				Name:   MaxLength,
1401				Rule:   2,
1402				Chain:  nil,
1403			}}}
1404	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1405		createError(reflect.ValueOf("hello"), c.Chain[0],
1406			"value length must be less than or equal to 2").Error())
1407}
1408
1409func TestValidatePointer_ArrayValid(t *testing.T) {
1410	c := Constraint{
1411		Target: "ptr",
1412		Name:   Null,
1413		Rule:   true,
1414		Chain: []Constraint{
1415			{
1416				Target: "ptr",
1417				Name:   UniqueItems,
1418				Rule:   "true",
1419				Chain:  nil,
1420			}}}
1421	require.Nil(t, validatePtr(reflect.ValueOf(&[]string{"1", "2"}), c))
1422}
1423
1424func TestValidatePointer_ArrayInvalid(t *testing.T) {
1425	z := []string{"1", "2", "2"}
1426	var x interface{} = &z
1427	c := Constraint{
1428		Target: "ptr",
1429		Name:   Null,
1430		Rule:   true,
1431		Chain: []Constraint{{
1432			Target: "ptr",
1433			Name:   UniqueItems,
1434			Rule:   true,
1435			Chain:  nil,
1436		}},
1437	}
1438	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1439		createError(reflect.ValueOf(z), c.Chain[0],
1440			fmt.Sprintf("all items in parameter %q must be unique; got:%v", c.Target, z)).Error())
1441}
1442
1443func TestValidatePointer_MapValid(t *testing.T) {
1444	c := Constraint{
1445		Target: "ptr",
1446		Name:   Null,
1447		Rule:   true,
1448		Chain: []Constraint{
1449			{
1450				Target: "ptr",
1451				Name:   UniqueItems,
1452				Rule:   true,
1453				Chain:  nil,
1454			}}}
1455	require.Nil(t, validatePtr(reflect.ValueOf(&map[interface{}]string{1: "1", "1": "2"}), c))
1456}
1457
1458func TestValidatePointer_MapInvalid(t *testing.T) {
1459	z := map[interface{}]string{1: "1", "1": "2", 1.3: "2"}
1460	var x interface{} = &z
1461	c := Constraint{
1462		Target: "ptr",
1463		Name:   Null,
1464		Rule:   true,
1465		Chain: []Constraint{{
1466			Target: "ptr",
1467			Name:   UniqueItems,
1468			Rule:   true,
1469			Chain:  nil,
1470		}},
1471	}
1472	require.Equal(t, strings.Contains(validatePtr(reflect.ValueOf(x), c).Error(),
1473		fmt.Sprintf("all items in parameter %q must be unique;", c.Target)), true)
1474}
1475
1476type Child struct {
1477	I string
1478}
1479type Product struct {
1480	C    *Child
1481	Str  *string
1482	Name string
1483	Arr  *[]string
1484	M    *map[string]string
1485	Num  *int32
1486}
1487
1488type Sample struct {
1489	M    *map[string]*string
1490	Name string
1491}
1492
1493func TestValidatePointer_StructWithError(t *testing.T) {
1494	s := "hello"
1495	var x interface{} = &Product{
1496		C:    &Child{"100"},
1497		Str:  &s,
1498		Name: "Gopher",
1499	}
1500	c := Constraint{
1501		"p", Null, "True",
1502		[]Constraint{
1503			{"C", Null, true,
1504				[]Constraint{
1505					{"I", MaxLength, 2, nil},
1506				}},
1507			{"Str", MaxLength, 2, nil},
1508			{"Name", MaxLength, 5, nil},
1509		},
1510	}
1511	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1512		createError(reflect.ValueOf("100"), c.Chain[0].Chain[0],
1513			"value length must be less than or equal to 2").Error())
1514}
1515
1516func TestValidatePointer_WithNilStruct(t *testing.T) {
1517	var p *Product
1518	var x interface{} = p
1519	c := Constraint{
1520		"p", Null, true,
1521		[]Constraint{
1522			{"C", Null, true,
1523				[]Constraint{
1524					{"I", Empty, true,
1525						[]Constraint{
1526							{"I", MaxLength, 5, nil},
1527						}},
1528				}},
1529			{"Str", MaxLength, 2, nil},
1530			{"Name", MaxLength, 5, nil},
1531		},
1532	}
1533	require.Equal(t, validatePtr(reflect.ValueOf(x), c).Error(),
1534		createError(reflect.ValueOf(x), c,
1535			fmt.Sprintf("value can not be null; required parameter")).Error())
1536}
1537
1538func TestValidatePointer_StructWithNoError(t *testing.T) {
1539	s := "hello"
1540	var x interface{} = &Product{
1541		C:    &Child{"100"},
1542		Str:  &s,
1543		Name: "Gopher",
1544	}
1545	c := Constraint{
1546		"p", Null, true,
1547		[]Constraint{
1548			{"C", Null, true,
1549				[]Constraint{
1550					{"I", Empty, true,
1551						[]Constraint{
1552							{"I", MaxLength, 5, nil},
1553						}},
1554				}},
1555		},
1556	}
1557	require.Nil(t, validatePtr(reflect.ValueOf(x), c))
1558}
1559
1560func TestValidateStruct_FieldNotExist(t *testing.T) {
1561	s := "hello"
1562	var x interface{} = Product{
1563		C:    &Child{"100"},
1564		Str:  &s,
1565		Name: "Gopher",
1566	}
1567	c := Constraint{
1568		"C", Null, true,
1569		[]Constraint{
1570			{"Name", Empty, true, nil},
1571		},
1572	}
1573	s = "Name"
1574	require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(),
1575		createError(reflect.ValueOf(Child{"100"}), c.Chain[0],
1576			fmt.Sprintf("field %q doesn't exist", s)).Error())
1577}
1578
1579func TestValidateStruct_WithChainConstraint(t *testing.T) {
1580	s := "hello"
1581	var x interface{} = Product{
1582		C:    &Child{"100"},
1583		Str:  &s,
1584		Name: "Gopher",
1585	}
1586	c := Constraint{
1587		"C", Null, true,
1588		[]Constraint{
1589			{"I", Empty, true,
1590				[]Constraint{
1591					{"I", MaxLength, 2, nil},
1592				}},
1593		},
1594	}
1595	require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(),
1596		createError(reflect.ValueOf("100"), c.Chain[0].Chain[0], "value length must be less than or equal to 2").Error())
1597}
1598
1599func TestValidateStruct_WithoutChainConstraint(t *testing.T) {
1600	s := "hello"
1601	var x interface{} = Product{
1602		C:    &Child{""},
1603		Str:  &s,
1604		Name: "Gopher",
1605	}
1606	c := Constraint{"C", Null, true,
1607		[]Constraint{
1608			{"I", Empty, true, nil}, // throw error for Empty
1609		}}
1610	require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(),
1611		createError(reflect.ValueOf(""), c.Chain[0], "value can not be null or empty; required parameter").Error())
1612}
1613
1614func TestValidateStruct_WithArrayNull(t *testing.T) {
1615	s := "hello"
1616	var x interface{} = Product{
1617		C:    &Child{""},
1618		Str:  &s,
1619		Name: "Gopher",
1620		Arr:  nil,
1621	}
1622	c := Constraint{"Arr", Null, true,
1623		[]Constraint{
1624			{"Arr", MaxItems, 4, nil},
1625			{"Arr", MinItems, 2, nil},
1626		},
1627	}
1628	require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(),
1629		createError(reflect.ValueOf(x.(Product).Arr), c, "value can not be null; required parameter").Error())
1630}
1631
1632func TestValidateStruct_WithArrayEmptyError(t *testing.T) {
1633	// arr := []string{}
1634	var x interface{} = Product{
1635		Arr: &[]string{},
1636	}
1637	c := Constraint{
1638		"Arr", Null, true,
1639		[]Constraint{
1640			{"Arr", Empty, true, nil},
1641			{"Arr", MaxItems, 4, nil},
1642			{"Arr", MinItems, 2, nil},
1643		}}
1644
1645	require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(),
1646		createError(reflect.ValueOf(*(x.(Product).Arr)), c.Chain[0],
1647			fmt.Sprintf("value can not be null or empty; required parameter")).Error())
1648}
1649
1650func TestValidateStruct_WithArrayEmptyWithoutError(t *testing.T) {
1651	var x interface{} = Product{
1652		Arr: &[]string{},
1653	}
1654	c := Constraint{
1655		"Arr", Null, true,
1656		[]Constraint{
1657			{"Arr", Empty, false, nil},
1658			{"Arr", MaxItems, 4, nil},
1659		},
1660	}
1661	require.Nil(t, validateStruct(reflect.ValueOf(x), c))
1662}
1663
1664func TestValidateStruct_ArrayWithError(t *testing.T) {
1665	arr := []string{"1", "1"}
1666	var x interface{} = Product{
1667		Arr: &arr,
1668	}
1669	c := Constraint{
1670		"Arr", Null, true,
1671		[]Constraint{
1672			{"Arr", Empty, true, nil},
1673			{"Arr", MaxItems, 4, nil},
1674			{"Arr", UniqueItems, true, nil},
1675		},
1676	}
1677	s := "Arr"
1678	require.Equal(t, validateStruct(reflect.ValueOf(x), c).Error(),
1679		createError(reflect.ValueOf(*(x.(Product).Arr)), c.Chain[2],
1680			fmt.Sprintf("all items in parameter %q must be unique; got:%v", s, *(x.(Product).Arr))).Error())
1681}
1682
1683func TestValidateStruct_MapWithError(t *testing.T) {
1684	m := map[string]string{
1685		"a": "hello",
1686		"b": "hello",
1687	}
1688	var x interface{} = Product{
1689		M: &m,
1690	}
1691	c := Constraint{
1692		"M", Null, true,
1693		[]Constraint{
1694			{"M", Empty, true, nil},
1695			{"M", MaxItems, 4, nil},
1696			{"M", UniqueItems, true, nil},
1697		},
1698	}
1699
1700	s := "M"
1701	require.Equal(t, strings.Contains(validateStruct(reflect.ValueOf(x), c).Error(),
1702		fmt.Sprintf("all items in parameter %q must be unique;", s)), true)
1703}
1704
1705func TestValidateStruct_MapWithNoError(t *testing.T) {
1706	m := map[string]string{}
1707	var x interface{} = Product{
1708		M: &m,
1709	}
1710	c := Constraint{
1711		"M", Null, true,
1712		[]Constraint{
1713			{"M", Empty, false, nil},
1714			{"M", MaxItems, 4, nil},
1715		},
1716	}
1717	require.Nil(t, validateStruct(reflect.ValueOf(x), c))
1718}
1719
1720func TestValidateStruct_MapNilNoError(t *testing.T) {
1721	var m map[string]string
1722	var x interface{} = Product{
1723		M: &m,
1724	}
1725	c := Constraint{
1726		"M", Null, false,
1727		[]Constraint{
1728			{"M", Empty, false, nil},
1729			{"M", MaxItems, 4, nil},
1730		},
1731	}
1732	require.Nil(t, validateStruct(reflect.ValueOf(x), c))
1733}
1734
1735func TestValidate_MapValidationWithError(t *testing.T) {
1736	var x1 interface{} = &Product{
1737		Arr: &[]string{"1", "2"},
1738		M:   &map[string]string{"a": "hello"},
1739	}
1740	s := "hello"
1741	var x2 interface{} = &Sample{
1742		M: &map[string]*string{"a": &s},
1743	}
1744	v := []Validation{
1745		{x1,
1746			[]Constraint{{"x1", Null, true,
1747				[]Constraint{
1748					{"Arr", Null, true,
1749						[]Constraint{
1750							{"Arr", Empty, true, nil},
1751							{"Arr", MaxItems, 4, nil},
1752							{"Arr", UniqueItems, true, nil},
1753						},
1754					},
1755					{"M", Null, false,
1756						[]Constraint{
1757							{"M", Empty, false, nil},
1758							{"M", MinItems, 1, nil},
1759							{"M", UniqueItems, true, nil},
1760						},
1761					},
1762				},
1763			}}},
1764		{x2,
1765			[]Constraint{
1766				{"x2", Null, true,
1767					[]Constraint{
1768						{"M", Null, false,
1769							[]Constraint{
1770								{"M", Empty, false, nil},
1771								{"M", MinItems, 2, nil},
1772								{"M", UniqueItems, true, nil},
1773							},
1774						},
1775					},
1776				},
1777				{"Name", Empty, true, nil},
1778			}},
1779	}
1780
1781	z := Validate(v).Error()
1782	require.Equal(t, strings.Contains(z, "minimum item limit is 2; got: 1"), true)
1783	require.Equal(t, strings.Contains(z, "MinItems"), true)
1784}
1785
1786func TestValidate_MapValidationWithoutError(t *testing.T) {
1787	var x1 interface{} = &Product{
1788		Arr: &[]string{"1", "2"},
1789		M:   &map[string]string{"a": "hello"},
1790	}
1791	s := "hello"
1792	var x2 interface{} = &Sample{
1793		M: &map[string]*string{"a": &s},
1794	}
1795	v := []Validation{
1796		{x1,
1797			[]Constraint{{"x1", Null, true,
1798				[]Constraint{
1799					{"Arr", Null, true,
1800						[]Constraint{
1801							{"Arr", Empty, true, nil},
1802							{"Arr", MaxItems, 4, nil},
1803							{"Arr", UniqueItems, true, nil},
1804						},
1805					},
1806					{"M", Null, false,
1807						[]Constraint{
1808							{"M", Empty, false, nil},
1809							{"M", MinItems, 1, nil},
1810							{"M", UniqueItems, true, nil},
1811							{"M", Pattern, "^[a-z]+$", nil},
1812						},
1813					},
1814				},
1815			}}},
1816		{x2,
1817			[]Constraint{
1818				{"x2", Null, true,
1819					[]Constraint{
1820						{"M", Null, false,
1821							[]Constraint{
1822								{"M", Empty, false, nil},
1823								{"M", MinItems, 1, nil},
1824								{"M", UniqueItems, true, nil},
1825								{"M", Pattern, "^[a-z]+$", nil},
1826							},
1827						},
1828					},
1829				},
1830				{"Name", Empty, true, nil},
1831			}},
1832	}
1833	require.Nil(t, Validate(v))
1834}
1835
1836func TestValidate_UnknownType(t *testing.T) {
1837	var c chan int
1838	v := []Validation{
1839		{c,
1840			[]Constraint{{"c", Null, true, nil}}},
1841	}
1842	require.Equal(t, Validate(v).Error(),
1843		createError(reflect.ValueOf(c), v[0].Constraints[0],
1844			fmt.Sprintf("unknown type %v", reflect.ValueOf(c).Kind())).Error())
1845}
1846
1847func TestValidate_example1(t *testing.T) {
1848	var x1 interface{} = Product{
1849		Arr: &[]string{"1", "1"},
1850		M:   &map[string]string{"a": "hello"},
1851	}
1852	s := "hello"
1853	var x2 interface{} = Sample{
1854		M: &map[string]*string{"a": &s},
1855	}
1856	v := []Validation{
1857		{x1,
1858			[]Constraint{{"Arr", Null, true,
1859				[]Constraint{
1860					{"Arr", Empty, true, nil},
1861					{"Arr", MaxItems, 4, nil},
1862					{"Arr", UniqueItems, true, nil},
1863				}},
1864				{"M", Null, false,
1865					[]Constraint{
1866						{"M", Empty, false, nil},
1867						{"M", MinItems, 1, nil},
1868						{"M", UniqueItems, true, nil},
1869					},
1870				},
1871			}},
1872		{x2,
1873			[]Constraint{
1874				{"M", Null, false,
1875					[]Constraint{
1876						{"M", Empty, false, nil},
1877						{"M", MinItems, 1, nil},
1878						{"M", UniqueItems, true, nil},
1879					},
1880				},
1881				{"Name", Empty, true, nil},
1882			}},
1883	}
1884	s = "Arr"
1885	require.Equal(t, Validate(v).Error(),
1886		createError(reflect.ValueOf([]string{"1", "1"}), v[0].Constraints[0].Chain[2],
1887			fmt.Sprintf("all items in parameter %q must be unique; got:%v", s, []string{"1", "1"})).Error())
1888}
1889
1890func TestValidate_Int(t *testing.T) {
1891	n := int32(100)
1892	v := []Validation{
1893		{n,
1894			[]Constraint{
1895				{"n", MultipleOf, 10, nil},
1896				{"n", ExclusiveMinimum, 100, nil},
1897			},
1898		},
1899	}
1900	require.Equal(t, Validate(v).Error(),
1901		createError(reflect.ValueOf(n), v[0].Constraints[1],
1902			"value must be greater than 100").Error())
1903}
1904
1905func TestValidate_IntPointer(t *testing.T) {
1906	n := int32(100)
1907	p := &n
1908	v := []Validation{
1909		{p,
1910			[]Constraint{
1911				{"p", Null, true, []Constraint{
1912					{"p", ExclusiveMinimum, 100, nil},
1913				}},
1914			},
1915		},
1916	}
1917	require.Equal(t, Validate(v).Error(),
1918		createError(reflect.ValueOf(n), v[0].Constraints[0].Chain[0],
1919			"value must be greater than 100").Error())
1920
1921	// required parameter
1922	p = nil
1923	v = []Validation{
1924		{p,
1925			[]Constraint{
1926				{"p", Null, true, []Constraint{
1927					{"p", ExclusiveMinimum, 100, nil},
1928				}},
1929			},
1930		},
1931	}
1932	require.Equal(t, Validate(v).Error(),
1933		createError(reflect.ValueOf(v[0].TargetValue), v[0].Constraints[0],
1934			"value can not be null; required parameter").Error())
1935
1936	// Not required
1937	p = nil
1938	v = []Validation{
1939		{p,
1940			[]Constraint{
1941				{"p", Null, false, []Constraint{
1942					{"p", ExclusiveMinimum, 100, nil},
1943				}},
1944			},
1945		},
1946	}
1947	require.Nil(t, Validate(v))
1948}
1949
1950func TestValidate_IntStruct(t *testing.T) {
1951	n := int32(100)
1952	p := &Product{
1953		Num: &n,
1954	}
1955
1956	v := []Validation{
1957		{p, []Constraint{{"p", Null, true,
1958			[]Constraint{
1959				{"Num", Null, true, []Constraint{
1960					{"Num", ExclusiveMinimum, 100, nil},
1961				}},
1962			},
1963		}}},
1964	}
1965	require.Equal(t, Validate(v).Error(),
1966		createError(reflect.ValueOf(n), v[0].Constraints[0].Chain[0].Chain[0],
1967			"value must be greater than 100").Error())
1968
1969	// required parameter
1970	p = &Product{}
1971	v = []Validation{
1972		{p, []Constraint{{"p", Null, true,
1973			[]Constraint{
1974				{"p.Num", Null, true, []Constraint{
1975					{"p.Num", ExclusiveMinimum, 100, nil},
1976				}},
1977			},
1978		}}},
1979	}
1980	require.Equal(t, Validate(v).Error(),
1981		createError(reflect.ValueOf(p.Num), v[0].Constraints[0].Chain[0],
1982			"value can not be null; required parameter").Error())
1983
1984	// Not required
1985	p = &Product{}
1986	v = []Validation{
1987		{p, []Constraint{{"p", Null, true,
1988			[]Constraint{
1989				{"Num", Null, false, []Constraint{
1990					{"Num", ExclusiveMinimum, 100, nil},
1991				}},
1992			},
1993		}}},
1994	}
1995	require.Nil(t, Validate(v))
1996
1997	// Parent not required
1998	p = nil
1999	v = []Validation{
2000		{p, []Constraint{{"p", Null, false,
2001			[]Constraint{
2002				{"Num", Null, false, []Constraint{
2003					{"Num", ExclusiveMinimum, 100, nil},
2004				}},
2005			},
2006		}}},
2007	}
2008	require.Nil(t, Validate(v))
2009}
2010
2011func TestValidate_String(t *testing.T) {
2012	s := "hello"
2013	v := []Validation{
2014		{s,
2015			[]Constraint{
2016				{"s", Empty, true, nil},
2017				{"s", Empty, true,
2018					[]Constraint{{"s", MaxLength, 3, nil}}},
2019			},
2020		},
2021	}
2022	require.Equal(t, Validate(v).Error(),
2023		createError(reflect.ValueOf(s), v[0].Constraints[1].Chain[0],
2024			"value length must be less than or equal to 3").Error())
2025
2026	// required parameter
2027	s = ""
2028	v = []Validation{
2029		{s,
2030			[]Constraint{
2031				{"s", Empty, true, nil},
2032				{"s", Empty, true,
2033					[]Constraint{{"s", MaxLength, 3, nil}}},
2034			},
2035		},
2036	}
2037	require.Equal(t, Validate(v).Error(),
2038		createError(reflect.ValueOf(s), v[0].Constraints[1],
2039			"value can not be null or empty; required parameter").Error())
2040
2041	// not required parameter
2042	s = ""
2043	v = []Validation{
2044		{s,
2045			[]Constraint{
2046				{"s", Empty, false, nil},
2047				{"s", Empty, false,
2048					[]Constraint{{"s", MaxLength, 3, nil}}},
2049			},
2050		},
2051	}
2052	require.Nil(t, Validate(v))
2053}
2054
2055func TestValidate_StringStruct(t *testing.T) {
2056	s := "hello"
2057	p := &Product{
2058		Str: &s,
2059	}
2060
2061	v := []Validation{
2062		{p, []Constraint{{"p", Null, true,
2063			[]Constraint{
2064				{"p.Str", Null, true, []Constraint{
2065					{"p.Str", Empty, true, nil},
2066					{"p.Str", MaxLength, 3, nil},
2067				}},
2068			},
2069		}}},
2070	}
2071	// e := ValidationError{
2072	// 	Constraint:  MaxLength,
2073	// 	Target:      "Str",
2074	// 	TargetValue: s,
2075	// 	Details:     fmt.Sprintf("value length must be less than 3", s),
2076	// }
2077	// if z := Validate(v); !reflect.DeepEqual(e, z) {
2078	// 	t.Fatalf("autorest/validation: Validate failed to return error \nexpect: %v\ngot: %v", e, z)
2079	// }
2080	require.Equal(t, Validate(v).Error(),
2081		createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[1],
2082			"value length must be less than or equal to 3").Error())
2083
2084	// required parameter - can't be Empty
2085	s = ""
2086	p = &Product{
2087		Str: &s,
2088	}
2089	v = []Validation{
2090		{p, []Constraint{{"p", Null, true,
2091			[]Constraint{
2092				{"Str", Null, true, []Constraint{
2093					{"Str", Empty, true, nil},
2094					{"Str", MaxLength, 3, nil},
2095				}},
2096			},
2097		}}},
2098	}
2099	require.Equal(t, Validate(v).Error(),
2100		createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[0],
2101			"value can not be null or empty; required parameter").Error())
2102
2103	// required parameter - can't be null
2104	p = &Product{}
2105	v = []Validation{
2106		{p, []Constraint{{"p", Null, true,
2107			[]Constraint{
2108				{"p.Str", Null, true, []Constraint{
2109					{"p.Str", Empty, true, nil},
2110					{"p.Str", MaxLength, 3, nil},
2111				}},
2112			},
2113		}}},
2114	}
2115	require.Equal(t, Validate(v).Error(),
2116		createError(reflect.ValueOf(p.Str), v[0].Constraints[0].Chain[0],
2117			"value can not be null; required parameter").Error())
2118
2119	// Not required
2120	p = &Product{}
2121	v = []Validation{
2122		{p, []Constraint{{"p", Null, true,
2123			[]Constraint{
2124				{"Str", Null, false, []Constraint{
2125					{"Str", Empty, true, nil},
2126					{"Str", MaxLength, 3, nil},
2127				}},
2128			},
2129		}}},
2130	}
2131	require.Nil(t, Validate(v))
2132
2133	// Parent not required
2134	p = nil
2135	v = []Validation{
2136		{p, []Constraint{{"p", Null, false,
2137			[]Constraint{
2138				{"Str", Null, true, []Constraint{
2139					{"Str", Empty, true, nil},
2140					{"Str", MaxLength, 3, nil},
2141				}},
2142			},
2143		}}},
2144	}
2145	require.Nil(t, Validate(v))
2146}
2147
2148func TestValidate_Array(t *testing.T) {
2149	s := []string{"hello"}
2150	v := []Validation{
2151		{s,
2152			[]Constraint{
2153				{"s", Null, true,
2154					[]Constraint{
2155						{"s", Empty, true, nil},
2156						{"s", MinItems, 2, nil},
2157					}},
2158			},
2159		},
2160	}
2161	require.Equal(t, Validate(v).Error(),
2162		createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[1],
2163			fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error())
2164
2165	// Empty array
2166	v = []Validation{
2167		{[]string{},
2168			[]Constraint{
2169				{"s", Null, true,
2170					[]Constraint{
2171						{"s", Empty, true, nil},
2172						{"s", MinItems, 2, nil}}},
2173			},
2174		},
2175	}
2176	require.Equal(t, Validate(v).Error(),
2177		createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0],
2178			"value can not be null or empty; required parameter").Error())
2179
2180	// null array
2181	var s1 []string
2182	v = []Validation{
2183		{s1,
2184			[]Constraint{
2185				{"s1", Null, true,
2186					[]Constraint{
2187						{"s1", Empty, true, nil},
2188						{"s1", MinItems, 2, nil}}},
2189			},
2190		},
2191	}
2192	require.Equal(t, Validate(v).Error(),
2193		createError(reflect.ValueOf(s1), v[0].Constraints[0],
2194			"value can not be null; required parameter").Error())
2195
2196	// not required parameter
2197	v = []Validation{
2198		{s1,
2199			[]Constraint{
2200				{"s1", Null, false,
2201					[]Constraint{
2202						{"s1", Empty, true, nil},
2203						{"s1", MinItems, 2, nil}}},
2204			},
2205		},
2206	}
2207	require.Nil(t, Validate(v))
2208}
2209
2210func TestValidate_ArrayPointer(t *testing.T) {
2211	s := []string{"hello"}
2212	v := []Validation{
2213		{&s,
2214			[]Constraint{
2215				{"s", Null, true,
2216					[]Constraint{
2217						{"s", Empty, true, nil},
2218						{"s", MinItems, 2, nil},
2219					}},
2220			},
2221		},
2222	}
2223	require.Equal(t, Validate(v).Error(),
2224		createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[1],
2225			fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error())
2226
2227	// Empty array
2228	v = []Validation{
2229		{&[]string{},
2230			[]Constraint{
2231				{"s", Null, true,
2232					[]Constraint{
2233						{"s", Empty, true, nil},
2234						{"s", MinItems, 2, nil}}},
2235			},
2236		},
2237	}
2238	require.Equal(t, Validate(v).Error(),
2239		createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0],
2240			"value can not be null or empty; required parameter").Error())
2241
2242	// null array
2243	var s1 *[]string
2244	v = []Validation{
2245		{s1,
2246			[]Constraint{
2247				{"s1", Null, true,
2248					[]Constraint{
2249						{"s1", Empty, true, nil},
2250						{"s1", MinItems, 2, nil}}},
2251			},
2252		},
2253	}
2254	require.Equal(t, Validate(v).Error(),
2255		createError(reflect.ValueOf(s1), v[0].Constraints[0],
2256			"value can not be null; required parameter").Error())
2257
2258	// not required parameter
2259	v = []Validation{
2260		{s1,
2261			[]Constraint{
2262				{"s1", Null, false,
2263					[]Constraint{
2264						{"s1", Empty, true, nil},
2265						{"s1", MinItems, 2, nil}}},
2266			},
2267		},
2268	}
2269	require.Nil(t, Validate(v))
2270}
2271
2272func TestValidate_ArrayInStruct(t *testing.T) {
2273	s := []string{"hello"}
2274	p := &Product{
2275		Arr: &s,
2276	}
2277
2278	v := []Validation{
2279		{p, []Constraint{{"p", Null, true,
2280			[]Constraint{
2281				{"p.Arr", Null, true, []Constraint{
2282					{"p.Arr", Empty, true, nil},
2283					{"p.Arr", MinItems, 2, nil},
2284				}},
2285			},
2286		}}},
2287	}
2288	require.Equal(t, Validate(v).Error(),
2289		createError(reflect.ValueOf(s), v[0].Constraints[0].Chain[0].Chain[1],
2290			fmt.Sprintf("minimum item limit is 2; got: %v", len(s))).Error())
2291
2292	// required parameter - can't be Empty
2293	p = &Product{
2294		Arr: &[]string{},
2295	}
2296	v = []Validation{
2297		{p, []Constraint{{"p", Null, true,
2298			[]Constraint{
2299				{"p.Arr", Null, true, []Constraint{
2300					{"p.Arr", Empty, true, nil},
2301					{"p.Arr", MinItems, 2, nil},
2302				}},
2303			},
2304		}}},
2305	}
2306	require.Equal(t, Validate(v).Error(),
2307		createError(reflect.ValueOf([]string{}), v[0].Constraints[0].Chain[0].Chain[0],
2308			"value can not be null or empty; required parameter").Error())
2309
2310	// required parameter - can't be null
2311	p = &Product{}
2312	v = []Validation{
2313		{p, []Constraint{{"p", Null, true,
2314			[]Constraint{
2315				{"p.Arr", Null, true, []Constraint{
2316					{"p.Arr", Empty, true, nil},
2317					{"p.Arr", MinItems, 2, nil},
2318				}},
2319			},
2320		}}},
2321	}
2322	require.Equal(t, Validate(v).Error(),
2323		createError(reflect.ValueOf(p.Arr), v[0].Constraints[0].Chain[0],
2324			"value can not be null; required parameter").Error())
2325
2326	// Not required
2327	v = []Validation{
2328		{&Product{}, []Constraint{{"p", Null, true,
2329			[]Constraint{
2330				{"Arr", Null, false, []Constraint{
2331					{"Arr", Empty, true, nil},
2332					{"Arr", MinItems, 2, nil},
2333				}},
2334			},
2335		}}},
2336	}
2337	require.Nil(t, Validate(v))
2338
2339	// Parent not required
2340	p = nil
2341	v = []Validation{
2342		{p, []Constraint{{"p", Null, false,
2343			[]Constraint{
2344				{"Arr", Null, true, []Constraint{
2345					{"Arr", Empty, true, nil},
2346					{"Arr", MinItems, 2, nil},
2347				}},
2348			},
2349		}}},
2350	}
2351	require.Nil(t, Validate(v))
2352}
2353
2354func TestValidate_StructInStruct(t *testing.T) {
2355	p := &Product{
2356		C: &Child{I: "hello"},
2357	}
2358	v := []Validation{
2359		{p, []Constraint{{"p", Null, true,
2360			[]Constraint{{"C", Null, true,
2361				[]Constraint{{"I", MinLength, 7, nil}}},
2362			},
2363		}}},
2364	}
2365	require.Equal(t, Validate(v).Error(),
2366		createError(reflect.ValueOf(p.C.I), v[0].Constraints[0].Chain[0].Chain[0],
2367			"value length must be greater than or equal to 7").Error())
2368
2369	// required parameter - can't be Empty
2370	p = &Product{
2371		C: &Child{I: ""},
2372	}
2373
2374	v = []Validation{
2375		{p, []Constraint{{"p", Null, true,
2376			[]Constraint{{"C", Null, true,
2377				[]Constraint{{"I", Empty, true, nil}}},
2378			},
2379		}}},
2380	}
2381	require.Equal(t, Validate(v).Error(),
2382		createError(reflect.ValueOf(p.C.I), v[0].Constraints[0].Chain[0].Chain[0],
2383			"value can not be null or empty; required parameter").Error())
2384
2385	// required parameter - can't be null
2386	p = &Product{}
2387	v = []Validation{
2388		{p, []Constraint{{"p", Null, true,
2389			[]Constraint{{"C", Null, true,
2390				[]Constraint{{"I", Empty, true, nil}}},
2391			},
2392		}}},
2393	}
2394	require.Equal(t, Validate(v).Error(),
2395		createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0],
2396			"value can not be null; required parameter").Error())
2397
2398	// Not required
2399	v = []Validation{
2400		{&Product{}, []Constraint{{"p", Null, true,
2401			[]Constraint{{"p.C", Null, false,
2402				[]Constraint{{"p.C.I", Empty, true, nil}}},
2403			},
2404		}}},
2405	}
2406	require.Nil(t, Validate(v))
2407
2408	// Parent not required
2409	p = nil
2410	v = []Validation{
2411		{p, []Constraint{{"p", Null, false,
2412			[]Constraint{{"p.C", Null, false,
2413				[]Constraint{{"p.C.I", Empty, true, nil}}},
2414			},
2415		}}},
2416	}
2417	require.Nil(t, Validate(v))
2418}
2419
2420func TestNewError(t *testing.T) {
2421	p := &Product{}
2422	v := []Validation{
2423		{p, []Constraint{{"p", Null, true,
2424			[]Constraint{{"p.C", Null, true,
2425				[]Constraint{{"p.C.I", Empty, true, nil}}},
2426			},
2427		}}},
2428	}
2429	err := createError(reflect.ValueOf(p.C), v[0].Constraints[0].Chain[0], "value can not be null; required parameter")
2430	z := fmt.Sprintf("batch.AccountClient#Create: Invalid input: %s",
2431		err.Error())
2432	require.Equal(t, NewError("batch.AccountClient", "Create", err.Error()).Error(), z)
2433}
2434