1package validator
2
3import (
4	"bytes"
5	sql "database/sql/driver"
6	"testing"
7	"time"
8)
9
10func BenchmarkFieldSuccess(b *testing.B) {
11	validate := New()
12	s := "1"
13
14	b.ResetTimer()
15	for n := 0; n < b.N; n++ {
16		_ = validate.Var(&s, "len=1")
17	}
18}
19
20func BenchmarkFieldSuccessParallel(b *testing.B) {
21	validate := New()
22	s := "1"
23
24	b.ResetTimer()
25	b.RunParallel(func(pb *testing.PB) {
26		for pb.Next() {
27			_ = validate.Var(&s, "len=1")
28		}
29	})
30}
31
32func BenchmarkFieldFailure(b *testing.B) {
33	validate := New()
34	s := "12"
35
36	b.ResetTimer()
37	for n := 0; n < b.N; n++ {
38		_ = validate.Var(&s, "len=1")
39	}
40}
41
42func BenchmarkFieldFailureParallel(b *testing.B) {
43	validate := New()
44	s := "12"
45
46	b.ResetTimer()
47	b.RunParallel(func(pb *testing.PB) {
48		for pb.Next() {
49			_ = validate.Var(&s, "len=1")
50		}
51	})
52}
53
54func BenchmarkFieldArrayDiveSuccess(b *testing.B) {
55	validate := New()
56	m := []string{"val1", "val2", "val3"}
57
58	b.ResetTimer()
59
60	for n := 0; n < b.N; n++ {
61		_ = validate.Var(m, "required,dive,required")
62	}
63}
64
65func BenchmarkFieldArrayDiveSuccessParallel(b *testing.B) {
66	validate := New()
67	m := []string{"val1", "val2", "val3"}
68
69	b.ResetTimer()
70	b.RunParallel(func(pb *testing.PB) {
71		for pb.Next() {
72			_ = validate.Var(m, "required,dive,required")
73		}
74	})
75}
76
77func BenchmarkFieldArrayDiveFailure(b *testing.B) {
78	validate := New()
79	m := []string{"val1", "", "val3"}
80
81	b.ResetTimer()
82	for n := 0; n < b.N; n++ {
83		_ = validate.Var(m, "required,dive,required")
84	}
85}
86
87func BenchmarkFieldArrayDiveFailureParallel(b *testing.B) {
88	validate := New()
89	m := []string{"val1", "", "val3"}
90
91	b.ResetTimer()
92	b.RunParallel(func(pb *testing.PB) {
93		for pb.Next() {
94			_ = validate.Var(m, "required,dive,required")
95		}
96	})
97}
98
99func BenchmarkFieldMapDiveSuccess(b *testing.B) {
100	validate := New()
101	m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
102
103	b.ResetTimer()
104
105	for n := 0; n < b.N; n++ {
106		_ = validate.Var(m, "required,dive,required")
107	}
108}
109
110func BenchmarkFieldMapDiveSuccessParallel(b *testing.B) {
111	validate := New()
112	m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
113
114	b.ResetTimer()
115	b.RunParallel(func(pb *testing.PB) {
116		for pb.Next() {
117			_ = validate.Var(m, "required,dive,required")
118		}
119	})
120}
121
122func BenchmarkFieldMapDiveFailure(b *testing.B) {
123	validate := New()
124	m := map[string]string{"": "", "val3": "val3"}
125
126	b.ResetTimer()
127	for n := 0; n < b.N; n++ {
128		_ = validate.Var(m, "required,dive,required")
129	}
130}
131
132func BenchmarkFieldMapDiveFailureParallel(b *testing.B) {
133	validate := New()
134	m := map[string]string{"": "", "val3": "val3"}
135
136	b.ResetTimer()
137	b.RunParallel(func(pb *testing.PB) {
138		for pb.Next() {
139			_ = validate.Var(m, "required,dive,required")
140		}
141	})
142}
143
144func BenchmarkFieldMapDiveWithKeysSuccess(b *testing.B) {
145	validate := New()
146	m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
147
148	b.ResetTimer()
149
150	for n := 0; n < b.N; n++ {
151		_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
152	}
153}
154
155func BenchmarkFieldMapDiveWithKeysSuccessParallel(b *testing.B) {
156	validate := New()
157	m := map[string]string{"val1": "val1", "val2": "val2", "val3": "val3"}
158
159	b.ResetTimer()
160	b.RunParallel(func(pb *testing.PB) {
161		for pb.Next() {
162			_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
163		}
164	})
165}
166
167func BenchmarkFieldMapDiveWithKeysFailure(b *testing.B) {
168	validate := New()
169	m := map[string]string{"": "", "val3": "val3"}
170
171	b.ResetTimer()
172	for n := 0; n < b.N; n++ {
173		_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
174	}
175}
176
177func BenchmarkFieldMapDiveWithKeysFailureParallel(b *testing.B) {
178	validate := New()
179	m := map[string]string{"": "", "val3": "val3"}
180
181	b.ResetTimer()
182	b.RunParallel(func(pb *testing.PB) {
183		for pb.Next() {
184			_ = validate.Var(m, "required,dive,keys,required,endkeys,required")
185		}
186	})
187}
188
189func BenchmarkFieldCustomTypeSuccess(b *testing.B) {
190	validate := New()
191	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
192	val := valuer{
193		Name: "1",
194	}
195
196	b.ResetTimer()
197	for n := 0; n < b.N; n++ {
198		_ = validate.Var(val, "len=1")
199	}
200}
201
202func BenchmarkFieldCustomTypeSuccessParallel(b *testing.B) {
203	validate := New()
204	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
205	val := valuer{
206		Name: "1",
207	}
208
209	b.ResetTimer()
210	b.RunParallel(func(pb *testing.PB) {
211		for pb.Next() {
212			_ = validate.Var(val, "len=1")
213		}
214	})
215}
216
217func BenchmarkFieldCustomTypeFailure(b *testing.B) {
218	validate := New()
219	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
220	val := valuer{}
221
222	b.ResetTimer()
223	for n := 0; n < b.N; n++ {
224		_ = validate.Var(val, "len=1")
225	}
226}
227
228func BenchmarkFieldCustomTypeFailureParallel(b *testing.B) {
229	validate := New()
230	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
231	val := valuer{}
232
233	b.ResetTimer()
234	b.RunParallel(func(pb *testing.PB) {
235		for pb.Next() {
236			_ = validate.Var(val, "len=1")
237		}
238	})
239}
240
241func BenchmarkFieldOrTagSuccess(b *testing.B) {
242	validate := New()
243	s := "rgba(0,0,0,1)"
244
245	b.ResetTimer()
246	for n := 0; n < b.N; n++ {
247		_ = validate.Var(s, "rgb|rgba")
248	}
249}
250
251func BenchmarkFieldOrTagSuccessParallel(b *testing.B) {
252	validate := New()
253	s := "rgba(0,0,0,1)"
254
255	b.ResetTimer()
256	b.RunParallel(func(pb *testing.PB) {
257		for pb.Next() {
258			_ = validate.Var(s, "rgb|rgba")
259		}
260	})
261}
262
263func BenchmarkFieldOrTagFailure(b *testing.B) {
264	validate := New()
265	s := "#000"
266
267	b.ResetTimer()
268	for n := 0; n < b.N; n++ {
269		_ = validate.Var(s, "rgb|rgba")
270	}
271}
272
273func BenchmarkFieldOrTagFailureParallel(b *testing.B) {
274	validate := New()
275	s := "#000"
276
277	b.ResetTimer()
278	b.RunParallel(func(pb *testing.PB) {
279		for pb.Next() {
280			_ = validate.Var(s, "rgb|rgba")
281		}
282	})
283}
284
285func BenchmarkStructLevelValidationSuccess(b *testing.B) {
286	validate := New()
287	validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
288
289	tst := TestStruct{
290		String: "good value",
291	}
292
293	b.ResetTimer()
294	for n := 0; n < b.N; n++ {
295		_ = validate.Struct(tst)
296	}
297}
298
299func BenchmarkStructLevelValidationSuccessParallel(b *testing.B) {
300	validate := New()
301	validate.RegisterStructValidation(StructValidationTestStructSuccess, TestStruct{})
302
303	tst := TestStruct{
304		String: "good value",
305	}
306
307	b.ResetTimer()
308	b.RunParallel(func(pb *testing.PB) {
309		for pb.Next() {
310			_ = validate.Struct(tst)
311		}
312	})
313}
314
315func BenchmarkStructLevelValidationFailure(b *testing.B) {
316	validate := New()
317	validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
318
319	tst := TestStruct{
320		String: "good value",
321	}
322
323	b.ResetTimer()
324	for n := 0; n < b.N; n++ {
325		_ = validate.Struct(tst)
326	}
327}
328
329func BenchmarkStructLevelValidationFailureParallel(b *testing.B) {
330	validate := New()
331	validate.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
332
333	tst := TestStruct{
334		String: "good value",
335	}
336
337	b.ResetTimer()
338	b.RunParallel(func(pb *testing.PB) {
339		for pb.Next() {
340			_ = validate.Struct(tst)
341		}
342	})
343}
344
345func BenchmarkStructSimpleCustomTypeSuccess(b *testing.B) {
346	validate := New()
347	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
348
349	val := valuer{
350		Name: "1",
351	}
352
353	type Foo struct {
354		Valuer   valuer `validate:"len=1"`
355		IntValue int    `validate:"min=5,max=10"`
356	}
357
358	validFoo := &Foo{Valuer: val, IntValue: 7}
359
360	b.ResetTimer()
361	for n := 0; n < b.N; n++ {
362		_ = validate.Struct(validFoo)
363	}
364}
365
366func BenchmarkStructSimpleCustomTypeSuccessParallel(b *testing.B) {
367	validate := New()
368	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
369	val := valuer{
370		Name: "1",
371	}
372
373	type Foo struct {
374		Valuer   valuer `validate:"len=1"`
375		IntValue int    `validate:"min=5,max=10"`
376	}
377	validFoo := &Foo{Valuer: val, IntValue: 7}
378
379	b.ResetTimer()
380	b.RunParallel(func(pb *testing.PB) {
381		for pb.Next() {
382			_ = validate.Struct(validFoo)
383		}
384	})
385}
386
387func BenchmarkStructSimpleCustomTypeFailure(b *testing.B) {
388	validate := New()
389	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
390
391	val := valuer{}
392
393	type Foo struct {
394		Valuer   valuer `validate:"len=1"`
395		IntValue int    `validate:"min=5,max=10"`
396	}
397	validFoo := &Foo{Valuer: val, IntValue: 3}
398
399	b.ResetTimer()
400	for n := 0; n < b.N; n++ {
401		_ = validate.Struct(validFoo)
402	}
403}
404
405func BenchmarkStructSimpleCustomTypeFailureParallel(b *testing.B) {
406	validate := New()
407	validate.RegisterCustomTypeFunc(ValidateValuerType, (*sql.Valuer)(nil), valuer{})
408
409	val := valuer{}
410
411	type Foo struct {
412		Valuer   valuer `validate:"len=1"`
413		IntValue int    `validate:"min=5,max=10"`
414	}
415	validFoo := &Foo{Valuer: val, IntValue: 3}
416
417	b.ResetTimer()
418	b.RunParallel(func(pb *testing.PB) {
419		for pb.Next() {
420			_ = validate.Struct(validate.Struct(validFoo))
421		}
422	})
423}
424
425func BenchmarkStructFilteredSuccess(b *testing.B) {
426	validate := New()
427
428	type Test struct {
429		Name     string `validate:"required"`
430		NickName string `validate:"required"`
431	}
432
433	test := &Test{
434		Name: "Joey Bloggs",
435	}
436	byts := []byte("Name")
437	fn := func(ns []byte) bool {
438		return !bytes.HasSuffix(ns, byts)
439	}
440
441	b.ResetTimer()
442	for n := 0; n < b.N; n++ {
443		_ = validate.StructFiltered(test, fn)
444	}
445}
446
447func BenchmarkStructFilteredSuccessParallel(b *testing.B) {
448	validate := New()
449
450	type Test struct {
451		Name     string `validate:"required"`
452		NickName string `validate:"required"`
453	}
454
455	test := &Test{
456		Name: "Joey Bloggs",
457	}
458	byts := []byte("Name")
459	fn := func(ns []byte) bool {
460		return !bytes.HasSuffix(ns, byts)
461	}
462
463	b.ResetTimer()
464	b.RunParallel(func(pb *testing.PB) {
465		for pb.Next() {
466			_ = validate.StructFiltered(test, fn)
467		}
468	})
469}
470
471func BenchmarkStructFilteredFailure(b *testing.B) {
472	validate := New()
473
474	type Test struct {
475		Name     string `validate:"required"`
476		NickName string `validate:"required"`
477	}
478
479	test := &Test{
480		Name: "Joey Bloggs",
481	}
482
483	byts := []byte("NickName")
484
485	fn := func(ns []byte) bool {
486		return !bytes.HasSuffix(ns, byts)
487	}
488
489	b.ResetTimer()
490	for n := 0; n < b.N; n++ {
491		_ = validate.StructFiltered(test, fn)
492	}
493}
494
495func BenchmarkStructFilteredFailureParallel(b *testing.B) {
496	validate := New()
497
498	type Test struct {
499		Name     string `validate:"required"`
500		NickName string `validate:"required"`
501	}
502
503	test := &Test{
504		Name: "Joey Bloggs",
505	}
506	byts := []byte("NickName")
507	fn := func(ns []byte) bool {
508		return !bytes.HasSuffix(ns, byts)
509	}
510
511	b.ResetTimer()
512	b.RunParallel(func(pb *testing.PB) {
513		for pb.Next() {
514			_ = validate.StructFiltered(test, fn)
515		}
516	})
517}
518
519func BenchmarkStructPartialSuccess(b *testing.B) {
520	validate := New()
521
522	type Test struct {
523		Name     string `validate:"required"`
524		NickName string `validate:"required"`
525	}
526
527	test := &Test{
528		Name: "Joey Bloggs",
529	}
530
531	b.ResetTimer()
532	for n := 0; n < b.N; n++ {
533		_ = validate.StructPartial(test, "Name")
534	}
535}
536
537func BenchmarkStructPartialSuccessParallel(b *testing.B) {
538	validate := New()
539
540	type Test struct {
541		Name     string `validate:"required"`
542		NickName string `validate:"required"`
543	}
544
545	test := &Test{
546		Name: "Joey Bloggs",
547	}
548
549	b.ResetTimer()
550	b.RunParallel(func(pb *testing.PB) {
551		for pb.Next() {
552			_ = validate.StructPartial(test, "Name")
553		}
554	})
555}
556
557func BenchmarkStructPartialFailure(b *testing.B) {
558	validate := New()
559
560	type Test struct {
561		Name     string `validate:"required"`
562		NickName string `validate:"required"`
563	}
564
565	test := &Test{
566		Name: "Joey Bloggs",
567	}
568
569	b.ResetTimer()
570	for n := 0; n < b.N; n++ {
571		_ = validate.StructPartial(test, "NickName")
572	}
573}
574
575func BenchmarkStructPartialFailureParallel(b *testing.B) {
576	validate := New()
577
578	type Test struct {
579		Name     string `validate:"required"`
580		NickName string `validate:"required"`
581	}
582
583	test := &Test{
584		Name: "Joey Bloggs",
585	}
586
587	b.ResetTimer()
588	b.RunParallel(func(pb *testing.PB) {
589		for pb.Next() {
590			_ = validate.StructPartial(test, "NickName")
591		}
592	})
593}
594
595func BenchmarkStructExceptSuccess(b *testing.B) {
596	validate := New()
597
598	type Test struct {
599		Name     string `validate:"required"`
600		NickName string `validate:"required"`
601	}
602
603	test := &Test{
604		Name: "Joey Bloggs",
605	}
606
607	b.ResetTimer()
608	for n := 0; n < b.N; n++ {
609		_ = validate.StructExcept(test, "Nickname")
610	}
611}
612
613func BenchmarkStructExceptSuccessParallel(b *testing.B) {
614	validate := New()
615
616	type Test struct {
617		Name     string `validate:"required"`
618		NickName string `validate:"required"`
619	}
620
621	test := &Test{
622		Name: "Joey Bloggs",
623	}
624
625	b.ResetTimer()
626	b.RunParallel(func(pb *testing.PB) {
627		for pb.Next() {
628			_ = validate.StructExcept(test, "NickName")
629		}
630	})
631}
632
633func BenchmarkStructExceptFailure(b *testing.B) {
634	validate := New()
635
636	type Test struct {
637		Name     string `validate:"required"`
638		NickName string `validate:"required"`
639	}
640
641	test := &Test{
642		Name: "Joey Bloggs",
643	}
644
645	b.ResetTimer()
646	for n := 0; n < b.N; n++ {
647		_ = validate.StructExcept(test, "Name")
648	}
649}
650
651func BenchmarkStructExceptFailureParallel(b *testing.B) {
652	validate := New()
653
654	type Test struct {
655		Name     string `validate:"required"`
656		NickName string `validate:"required"`
657	}
658
659	test := &Test{
660		Name: "Joey Bloggs",
661	}
662
663	b.ResetTimer()
664	b.RunParallel(func(pb *testing.PB) {
665		for pb.Next() {
666			_ = validate.StructExcept(test, "Name")
667		}
668	})
669}
670
671func BenchmarkStructSimpleCrossFieldSuccess(b *testing.B) {
672	validate := New()
673
674	type Test struct {
675		Start time.Time
676		End   time.Time `validate:"gtfield=Start"`
677	}
678
679	now := time.Now().UTC()
680	then := now.Add(time.Hour * 5)
681	test := &Test{
682		Start: now,
683		End:   then,
684	}
685
686	b.ResetTimer()
687	for n := 0; n < b.N; n++ {
688		_ = validate.Struct(test)
689	}
690}
691
692func BenchmarkStructSimpleCrossFieldSuccessParallel(b *testing.B) {
693	validate := New()
694
695	type Test struct {
696		Start time.Time
697		End   time.Time `validate:"gtfield=Start"`
698	}
699
700	now := time.Now().UTC()
701	then := now.Add(time.Hour * 5)
702	test := &Test{
703		Start: now,
704		End:   then,
705	}
706
707	b.ResetTimer()
708	b.RunParallel(func(pb *testing.PB) {
709		for pb.Next() {
710			_ = validate.Struct(test)
711		}
712	})
713}
714
715func BenchmarkStructSimpleCrossFieldFailure(b *testing.B) {
716	validate := New()
717
718	type Test struct {
719		Start time.Time
720		End   time.Time `validate:"gtfield=Start"`
721	}
722
723	now := time.Now().UTC()
724	then := now.Add(time.Hour * -5)
725
726	test := &Test{
727		Start: now,
728		End:   then,
729	}
730
731	b.ResetTimer()
732	for n := 0; n < b.N; n++ {
733		_ = validate.Struct(test)
734	}
735}
736
737func BenchmarkStructSimpleCrossFieldFailureParallel(b *testing.B) {
738	validate := New()
739
740	type Test struct {
741		Start time.Time
742		End   time.Time `validate:"gtfield=Start"`
743	}
744
745	now := time.Now().UTC()
746	then := now.Add(time.Hour * -5)
747	test := &Test{
748		Start: now,
749		End:   then,
750	}
751	b.ResetTimer()
752	b.RunParallel(func(pb *testing.PB) {
753		for pb.Next() {
754			_ = validate.Struct(test)
755		}
756	})
757}
758
759func BenchmarkStructSimpleCrossStructCrossFieldSuccess(b *testing.B) {
760	validate := New()
761
762	type Inner struct {
763		Start time.Time
764	}
765
766	type Outer struct {
767		Inner     *Inner
768		CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
769	}
770
771	now := time.Now().UTC()
772	inner := &Inner{
773		Start: now,
774	}
775	outer := &Outer{
776		Inner:     inner,
777		CreatedAt: now,
778	}
779
780	b.ResetTimer()
781	for n := 0; n < b.N; n++ {
782		_ = validate.Struct(outer)
783	}
784}
785
786func BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel(b *testing.B) {
787	validate := New()
788
789	type Inner struct {
790		Start time.Time
791	}
792
793	type Outer struct {
794		Inner     *Inner
795		CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
796	}
797
798	now := time.Now().UTC()
799	inner := &Inner{
800		Start: now,
801	}
802	outer := &Outer{
803		Inner:     inner,
804		CreatedAt: now,
805	}
806
807	b.ResetTimer()
808	b.RunParallel(func(pb *testing.PB) {
809		for pb.Next() {
810			_ = validate.Struct(outer)
811		}
812	})
813}
814
815func BenchmarkStructSimpleCrossStructCrossFieldFailure(b *testing.B) {
816	validate := New()
817	type Inner struct {
818		Start time.Time
819	}
820
821	type Outer struct {
822		Inner     *Inner
823		CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
824	}
825
826	now := time.Now().UTC()
827	then := now.Add(time.Hour * 5)
828
829	inner := &Inner{
830		Start: then,
831	}
832
833	outer := &Outer{
834		Inner:     inner,
835		CreatedAt: now,
836	}
837
838	b.ResetTimer()
839	for n := 0; n < b.N; n++ {
840		_ = validate.Struct(outer)
841	}
842}
843
844func BenchmarkStructSimpleCrossStructCrossFieldFailureParallel(b *testing.B) {
845	validate := New()
846
847	type Inner struct {
848		Start time.Time
849	}
850
851	type Outer struct {
852		Inner     *Inner
853		CreatedAt time.Time `validate:"eqcsfield=Inner.Start"`
854	}
855
856	now := time.Now().UTC()
857	then := now.Add(time.Hour * 5)
858
859	inner := &Inner{
860		Start: then,
861	}
862
863	outer := &Outer{
864		Inner:     inner,
865		CreatedAt: now,
866	}
867
868	b.ResetTimer()
869	b.RunParallel(func(pb *testing.PB) {
870		for pb.Next() {
871			_ = validate.Struct(outer)
872		}
873	})
874}
875
876func BenchmarkStructSimpleSuccess(b *testing.B) {
877	validate := New()
878	type Foo struct {
879		StringValue string `validate:"min=5,max=10"`
880		IntValue    int    `validate:"min=5,max=10"`
881	}
882
883	validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
884
885	b.ResetTimer()
886	for n := 0; n < b.N; n++ {
887		_ = validate.Struct(validFoo)
888	}
889}
890
891func BenchmarkStructSimpleSuccessParallel(b *testing.B) {
892	validate := New()
893	type Foo struct {
894		StringValue string `validate:"min=5,max=10"`
895		IntValue    int    `validate:"min=5,max=10"`
896	}
897	validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
898
899	b.ResetTimer()
900	b.RunParallel(func(pb *testing.PB) {
901		for pb.Next() {
902			_ = validate.Struct(validFoo)
903		}
904	})
905}
906
907func BenchmarkStructSimpleFailure(b *testing.B) {
908	validate := New()
909	type Foo struct {
910		StringValue string `validate:"min=5,max=10"`
911		IntValue    int    `validate:"min=5,max=10"`
912	}
913
914	invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
915
916	b.ResetTimer()
917	for n := 0; n < b.N; n++ {
918		_ = validate.Struct(invalidFoo)
919	}
920}
921
922func BenchmarkStructSimpleFailureParallel(b *testing.B) {
923	validate := New()
924	type Foo struct {
925		StringValue string `validate:"min=5,max=10"`
926		IntValue    int    `validate:"min=5,max=10"`
927	}
928
929	invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
930
931	b.ResetTimer()
932	b.RunParallel(func(pb *testing.PB) {
933		for pb.Next() {
934			_ = validate.Struct(invalidFoo)
935		}
936	})
937}
938
939func BenchmarkStructComplexSuccess(b *testing.B) {
940	validate := New()
941	tSuccess := &TestString{
942		Required:  "Required",
943		Len:       "length==10",
944		Min:       "min=1",
945		Max:       "1234567890",
946		MinMax:    "12345",
947		Lt:        "012345678",
948		Lte:       "0123456789",
949		Gt:        "01234567890",
950		Gte:       "0123456789",
951		OmitEmpty: "",
952		Sub: &SubTest{
953			Test: "1",
954		},
955		SubIgnore: &SubTest{
956			Test: "",
957		},
958		Anonymous: struct {
959			A string `validate:"required"`
960		}{
961			A: "1",
962		},
963		Iface: &Impl{
964			F: "123",
965		},
966	}
967
968	b.ResetTimer()
969	for n := 0; n < b.N; n++ {
970		_ = validate.Struct(tSuccess)
971	}
972}
973
974func BenchmarkStructComplexSuccessParallel(b *testing.B) {
975	validate := New()
976	tSuccess := &TestString{
977		Required:  "Required",
978		Len:       "length==10",
979		Min:       "min=1",
980		Max:       "1234567890",
981		MinMax:    "12345",
982		Lt:        "012345678",
983		Lte:       "0123456789",
984		Gt:        "01234567890",
985		Gte:       "0123456789",
986		OmitEmpty: "",
987		Sub: &SubTest{
988			Test: "1",
989		},
990		SubIgnore: &SubTest{
991			Test: "",
992		},
993		Anonymous: struct {
994			A string `validate:"required"`
995		}{
996			A: "1",
997		},
998		Iface: &Impl{
999			F: "123",
1000		},
1001	}
1002
1003	b.ResetTimer()
1004	b.RunParallel(func(pb *testing.PB) {
1005		for pb.Next() {
1006			_ = validate.Struct(tSuccess)
1007		}
1008	})
1009}
1010
1011func BenchmarkStructComplexFailure(b *testing.B) {
1012	validate := New()
1013	tFail := &TestString{
1014		Required:  "",
1015		Len:       "",
1016		Min:       "",
1017		Max:       "12345678901",
1018		MinMax:    "",
1019		Lt:        "0123456789",
1020		Lte:       "01234567890",
1021		Gt:        "1",
1022		Gte:       "1",
1023		OmitEmpty: "12345678901",
1024		Sub: &SubTest{
1025			Test: "",
1026		},
1027		Anonymous: struct {
1028			A string `validate:"required"`
1029		}{
1030			A: "",
1031		},
1032		Iface: &Impl{
1033			F: "12",
1034		},
1035	}
1036
1037	b.ResetTimer()
1038	for n := 0; n < b.N; n++ {
1039		_ = validate.Struct(tFail)
1040	}
1041}
1042
1043func BenchmarkStructComplexFailureParallel(b *testing.B) {
1044	validate := New()
1045	tFail := &TestString{
1046		Required:  "",
1047		Len:       "",
1048		Min:       "",
1049		Max:       "12345678901",
1050		MinMax:    "",
1051		Lt:        "0123456789",
1052		Lte:       "01234567890",
1053		Gt:        "1",
1054		Gte:       "1",
1055		OmitEmpty: "12345678901",
1056		Sub: &SubTest{
1057			Test: "",
1058		},
1059		Anonymous: struct {
1060			A string `validate:"required"`
1061		}{
1062			A: "",
1063		},
1064		Iface: &Impl{
1065			F: "12",
1066		},
1067	}
1068
1069	b.ResetTimer()
1070	b.RunParallel(func(pb *testing.PB) {
1071		for pb.Next() {
1072			_ = validate.Struct(tFail)
1073		}
1074	})
1075}
1076
1077type TestOneof struct {
1078	Color string `validate:"oneof=red green"`
1079}
1080
1081func BenchmarkOneof(b *testing.B) {
1082	w := &TestOneof{Color: "green"}
1083	val := New()
1084	for i := 0; i < b.N; i++ {
1085		_ = val.Struct(w)
1086	}
1087}
1088
1089func BenchmarkOneofParallel(b *testing.B) {
1090	w := &TestOneof{Color: "green"}
1091	val := New()
1092
1093	b.ResetTimer()
1094	b.RunParallel(func(pb *testing.PB) {
1095		for pb.Next() {
1096			_ = val.Struct(w)
1097		}
1098	})
1099}
1100