Codebase list golang-github-go-playground-validator-v10 / 11e5ebe
Merge pull request #317 from go-playground/add-unique Add unique Dean Karn authored 6 years ago GitHub committed 6 years ago
4 changed file(s) with 122 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
6464
6565 Benchmarks
6666 ------
67 ###### Run on Dell XPS 15 i7-7700HQ 32GB Go version go1.8.3 linux/amd64
67 ###### Run on MacBook Pro (15-inch, 2017) Go version go1.9.1 linux/amd64
6868 ```go
69 go test -run=XXX -bench=. -benchmem=true
70 BenchmarkFieldSuccess-8 20000000 88.3 ns/op 0 B/op 0 allocs/op
71 BenchmarkFieldSuccessParallel-8 50000000 30.4 ns/op 0 B/op 0 allocs/op
72 BenchmarkFieldFailure-8 3000000 428 ns/op 208 B/op 4 allocs/op
73 BenchmarkFieldFailureParallel-8 20000000 96.0 ns/op 208 B/op 4 allocs/op
74 BenchmarkFieldDiveSuccess-8 2000000 695 ns/op 201 B/op 11 allocs/op
75 BenchmarkFieldDiveSuccessParallel-8 10000000 205 ns/op 201 B/op 11 allocs/op
76 BenchmarkFieldDiveFailure-8 1000000 1083 ns/op 412 B/op 16 allocs/op
77 BenchmarkFieldDiveFailureParallel-8 5000000 278 ns/op 413 B/op 16 allocs/op
78 BenchmarkFieldCustomTypeSuccess-8 10000000 229 ns/op 32 B/op 2 allocs/op
79 BenchmarkFieldCustomTypeSuccessParallel-8 20000000 72.4 ns/op 32 B/op 2 allocs/op
80 BenchmarkFieldCustomTypeFailure-8 5000000 377 ns/op 208 B/op 4 allocs/op
81 BenchmarkFieldCustomTypeFailureParallel-8 20000000 93.0 ns/op 208 B/op 4 allocs/op
82 BenchmarkFieldOrTagSuccess-8 2000000 767 ns/op 16 B/op 1 allocs/op
83 BenchmarkFieldOrTagSuccessParallel-8 3000000 425 ns/op 16 B/op 1 allocs/op
84 BenchmarkFieldOrTagFailure-8 2000000 548 ns/op 224 B/op 5 allocs/op
85 BenchmarkFieldOrTagFailureParallel-8 3000000 411 ns/op 224 B/op 5 allocs/op
86 BenchmarkStructLevelValidationSuccess-8 10000000 219 ns/op 32 B/op 2 allocs/op
87 BenchmarkStructLevelValidationSuccessParallel-8 20000000 69.2 ns/op 32 B/op 2 allocs/op
88 BenchmarkStructLevelValidationFailure-8 2000000 628 ns/op 304 B/op 8 allocs/op
89 BenchmarkStructLevelValidationFailureParallel-8 10000000 165 ns/op 304 B/op 8 allocs/op
90 BenchmarkStructSimpleCustomTypeSuccess-8 3000000 411 ns/op 32 B/op 2 allocs/op
91 BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 122 ns/op 32 B/op 2 allocs/op
92 BenchmarkStructSimpleCustomTypeFailure-8 1000000 1022 ns/op 424 B/op 9 allocs/op
93 BenchmarkStructSimpleCustomTypeFailureParallel-8 10000000 228 ns/op 440 B/op 10 allocs/op
94 BenchmarkStructFilteredSuccess-8 2000000 737 ns/op 288 B/op 9 allocs/op
95 BenchmarkStructFilteredSuccessParallel-8 10000000 192 ns/op 288 B/op 9 allocs/op
96 BenchmarkStructFilteredFailure-8 3000000 583 ns/op 256 B/op 7 allocs/op
97 BenchmarkStructFilteredFailureParallel-8 10000000 152 ns/op 256 B/op 7 allocs/op
98 BenchmarkStructPartialSuccess-8 2000000 731 ns/op 256 B/op 6 allocs/op
99 BenchmarkStructPartialSuccessParallel-8 10000000 173 ns/op 256 B/op 6 allocs/op
100 BenchmarkStructPartialFailure-8 1000000 1164 ns/op 480 B/op 11 allocs/op
101 BenchmarkStructPartialFailureParallel-8 5000000 253 ns/op 480 B/op 11 allocs/op
102 BenchmarkStructExceptSuccess-8 1000000 1337 ns/op 496 B/op 12 allocs/op
103 BenchmarkStructExceptSuccessParallel-8 10000000 153 ns/op 240 B/op 5 allocs/op
104 BenchmarkStructExceptFailure-8 2000000 954 ns/op 464 B/op 10 allocs/op
105 BenchmarkStructExceptFailureParallel-8 5000000 234 ns/op 464 B/op 10 allocs/op
106 BenchmarkStructSimpleCrossFieldSuccess-8 3000000 420 ns/op 72 B/op 3 allocs/op
107 BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 125 ns/op 72 B/op 3 allocs/op
108 BenchmarkStructSimpleCrossFieldFailure-8 2000000 790 ns/op 304 B/op 8 allocs/op
109 BenchmarkStructSimpleCrossFieldFailureParallel-8 10000000 205 ns/op 304 B/op 8 allocs/op
110 BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 2000000 611 ns/op 80 B/op 4 allocs/op
111 BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 172 ns/op 80 B/op 4 allocs/op
112 BenchmarkStructSimpleCrossStructCrossFieldFailure-8 1000000 1112 ns/op 320 B/op 9 allocs/op
113 BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 258 ns/op 320 B/op 9 allocs/op
114 BenchmarkStructSimpleSuccess-8 5000000 263 ns/op 0 B/op 0 allocs/op
115 BenchmarkStructSimpleSuccessParallel-8 20000000 83.1 ns/op 0 B/op 0 allocs/op
116 BenchmarkStructSimpleFailure-8 2000000 964 ns/op 424 B/op 9 allocs/op
117 BenchmarkStructSimpleFailureParallel-8 10000000 212 ns/op 424 B/op 9 allocs/op
118 BenchmarkStructComplexSuccess-8 1000000 1504 ns/op 128 B/op 8 allocs/op
119 BenchmarkStructComplexSuccessParallel-8 3000000 427 ns/op 128 B/op 8 allocs/op
120 BenchmarkStructComplexFailure-8 300000 7585 ns/op 3041 B/op 53 allocs/op
121 BenchmarkStructComplexFailureParallel-8 1000000 1387 ns/op 3041 B/op 53 allocs/op
69 go test -bench=. -benchmem=true
70 BenchmarkFieldSuccess-8 20000000 87.2 ns/op 0 B/op 0 allocs/op
71 BenchmarkFieldSuccessParallel-8 50000000 26.1 ns/op 0 B/op 0 allocs/op
72 BenchmarkFieldFailure-8 5000000 299 ns/op 208 B/op 4 allocs/op
73 BenchmarkFieldFailureParallel-8 20000000 100 ns/op 208 B/op 4 allocs/op
74 BenchmarkFieldDiveSuccess-8 2000000 645 ns/op 201 B/op 11 allocs/op
75 BenchmarkFieldDiveSuccessParallel-8 10000000 198 ns/op 201 B/op 11 allocs/op
76 BenchmarkFieldDiveFailure-8 2000000 876 ns/op 412 B/op 16 allocs/op
77 BenchmarkFieldDiveFailureParallel-8 5000000 268 ns/op 413 B/op 16 allocs/op
78 BenchmarkFieldCustomTypeSuccess-8 10000000 228 ns/op 32 B/op 2 allocs/op
79 BenchmarkFieldCustomTypeSuccessParallel-8 20000000 70.0 ns/op 32 B/op 2 allocs/op
80 BenchmarkFieldCustomTypeFailure-8 5000000 286 ns/op 208 B/op 4 allocs/op
81 BenchmarkFieldCustomTypeFailureParallel-8 20000000 95.6 ns/op 208 B/op 4 allocs/op
82 BenchmarkFieldOrTagSuccess-8 2000000 857 ns/op 16 B/op 1 allocs/op
83 BenchmarkFieldOrTagSuccessParallel-8 3000000 397 ns/op 16 B/op 1 allocs/op
84 BenchmarkFieldOrTagFailure-8 3000000 495 ns/op 224 B/op 5 allocs/op
85 BenchmarkFieldOrTagFailureParallel-8 5000000 376 ns/op 224 B/op 5 allocs/op
86 BenchmarkStructLevelValidationSuccess-8 10000000 226 ns/op 32 B/op 2 allocs/op
87 BenchmarkStructLevelValidationSuccessParallel-8 20000000 68.4 ns/op 32 B/op 2 allocs/op
88 BenchmarkStructLevelValidationFailure-8 3000000 497 ns/op 304 B/op 8 allocs/op
89 BenchmarkStructLevelValidationFailureParallel-8 10000000 170 ns/op 304 B/op 8 allocs/op
90 BenchmarkStructSimpleCustomTypeSuccess-8 3000000 420 ns/op 32 B/op 2 allocs/op
91 BenchmarkStructSimpleCustomTypeSuccessParallel-8 20000000 124 ns/op 32 B/op 2 allocs/op
92 BenchmarkStructSimpleCustomTypeFailure-8 2000000 681 ns/op 424 B/op 9 allocs/op
93 BenchmarkStructSimpleCustomTypeFailureParallel-8 10000000 244 ns/op 440 B/op 10 allocs/op
94 BenchmarkStructFilteredSuccess-8 2000000 659 ns/op 288 B/op 9 allocs/op
95 BenchmarkStructFilteredSuccessParallel-8 10000000 211 ns/op 288 B/op 9 allocs/op
96 BenchmarkStructFilteredFailure-8 3000000 482 ns/op 256 B/op 7 allocs/op
97 BenchmarkStructFilteredFailureParallel-8 10000000 162 ns/op 256 B/op 7 allocs/op
98 BenchmarkStructPartialSuccess-8 3000000 564 ns/op 256 B/op 6 allocs/op
99 BenchmarkStructPartialSuccessParallel-8 10000000 180 ns/op 256 B/op 6 allocs/op
100 BenchmarkStructPartialFailure-8 2000000 779 ns/op 480 B/op 11 allocs/op
101 BenchmarkStructPartialFailureParallel-8 5000000 268 ns/op 480 B/op 11 allocs/op
102 BenchmarkStructExceptSuccess-8 2000000 879 ns/op 496 B/op 12 allocs/op
103 BenchmarkStructExceptSuccessParallel-8 10000000 163 ns/op 240 B/op 5 allocs/op
104 BenchmarkStructExceptFailure-8 2000000 734 ns/op 464 B/op 10 allocs/op
105 BenchmarkStructExceptFailureParallel-8 5000000 259 ns/op 464 B/op 10 allocs/op
106 BenchmarkStructSimpleCrossFieldSuccess-8 3000000 432 ns/op 72 B/op 3 allocs/op
107 BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 129 ns/op 72 B/op 3 allocs/op
108 BenchmarkStructSimpleCrossFieldFailure-8 2000000 671 ns/op 304 B/op 8 allocs/op
109 BenchmarkStructSimpleCrossFieldFailureParallel-8 10000000 229 ns/op 304 B/op 8 allocs/op
110 BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 2000000 628 ns/op 80 B/op 4 allocs/op
111 BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 182 ns/op 80 B/op 4 allocs/op
112 BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 872 ns/op 320 B/op 9 allocs/op
113 BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 267 ns/op 320 B/op 9 allocs/op
114 BenchmarkStructSimpleSuccess-8 5000000 274 ns/op 0 B/op 0 allocs/op
115 BenchmarkStructSimpleSuccessParallel-8 20000000 79.0 ns/op 0 B/op 0 allocs/op
116 BenchmarkStructSimpleFailure-8 2000000 647 ns/op 424 B/op 9 allocs/op
117 BenchmarkStructSimpleFailureParallel-8 10000000 224 ns/op 424 B/op 9 allocs/op
118 BenchmarkStructComplexSuccess-8 1000000 1557 ns/op 128 B/op 8 allocs/op
119 BenchmarkStructComplexSuccessParallel-8 3000000 473 ns/op 128 B/op 8 allocs/op
120 BenchmarkStructComplexFailure-8 300000 4373 ns/op 3041 B/op 53 allocs/op
121 BenchmarkStructComplexFailureParallel-8 1000000 1554 ns/op 3041 B/op 53 allocs/op
122122 ```
123123
124124 Complementary Software
127127 Here is a list of software that complements using this library either pre or post validation.
128128
129129 * [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
130 * [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags.
130 * [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects
131131
132132 How to Contribute
133133 ------
130130 "mac": isMAC,
131131 "hostname": isHostname,
132132 "fqdn": isFQDN,
133 "unique": isUnique,
133134 }
134135 )
136
137 // isUnique is the validation function for validating if each array|slice element is unique
138 func isUnique(fl FieldLevel) bool {
139
140 field := fl.Field()
141 v := reflect.ValueOf(struct{}{})
142
143 switch field.Kind() {
144 case reflect.Slice, reflect.Array:
145 m := reflect.MakeMap(reflect.MapOf(fl.Field().Type().Elem(), v.Type()))
146
147 for i := 0; i < field.Len(); i++ {
148 m.SetMapIndex(field.Index(i), v)
149 }
150 return field.Len() == m.Len()
151 default:
152 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
153 }
154 }
135155
136156 // IsMAC is the validation function for validating if the field's value is a valid MAC address.
137157 func isMAC(fl FieldLevel) bool {
467467
468468 Usage: ltecsfield=InnerStructField.Field
469469
470 Unique
471
472 For arrays & slices, unique will ensure that there are no duplicates.
473
474 Usage: unique
475
470476 Alpha Only
471477
472478 This validates that a string value contains ASCII alpha characters only
72717271 Equal(t, fe.Namespace(), "Test2.inner")
72727272 Equal(t, fe.Tag(), "isdefault")
72737273 }
7274
7275 func TestUniqueValidation(t *testing.T) {
7276 tests := []struct {
7277 param interface{}
7278 expected bool
7279 }{
7280 {[]string{"a", "b"}, true},
7281 {[]int{1, 2}, true},
7282 {[]float64{1, 2}, true},
7283 {[]interface{}{"a", "b"}, true},
7284 {[]interface{}{"a", 1}, true},
7285 {[]float64{1, 1}, false},
7286 {[]int{1, 1}, false},
7287 {[]string{"a", "a"}, false},
7288 {[]interface{}{"a", "a"}, false},
7289 {[]interface{}{"a", 1, "b", 1}, false},
7290 }
7291
7292 validate := New()
7293
7294 for i, test := range tests {
7295
7296 errs := validate.Var(test.param, "unique")
7297
7298 if test.expected {
7299 if !IsEqual(errs, nil) {
7300 t.Fatalf("Index: %d unique failed Error: %v", i, errs)
7301 }
7302 } else {
7303 if IsEqual(errs, nil) {
7304 t.Fatalf("Index: %d unique failed Error: %v", i, errs)
7305 } else {
7306 val := getError(errs, "", "")
7307 if val.Tag() != "unique" {
7308 t.Fatalf("Index: %d unique failed Error: %v", i, errs)
7309 }
7310 }
7311 }
7312 }
7313 PanicMatches(t, func() { validate.Var(1.0, "unique") }, "Bad field type float64")
7314 }