diff --git a/.gitignore b/.gitignore index 792ca00d..6e43fac0 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ # Folders _obj _test +bin # Architecture specific extensions/prefixes *.[568vq] @@ -26,4 +27,4 @@ _testmain.go *.out *.txt cover.html -README.html \ No newline at end of file +README.html diff --git a/baked_in.go b/baked_in.go index ef23bdd3..ac9145df 100644 --- a/baked_in.go +++ b/baked_in.go @@ -1145,7 +1145,7 @@ func isEq(fl FieldLevel) bool { return int64(field.Len()) == p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) + p := asIntFromType(field.Type(), param) return field.Int() == p @@ -1659,7 +1659,7 @@ func isGte(fl FieldLevel) bool { return int64(field.Len()) >= p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) + p := asIntFromType(field.Type(), param) return field.Int() >= p @@ -1706,7 +1706,7 @@ func isGt(fl FieldLevel) bool { return int64(field.Len()) > p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) + p := asIntFromType(field.Type(), param) return field.Int() > p @@ -1749,7 +1749,7 @@ func hasLengthOf(fl FieldLevel) bool { return int64(field.Len()) == p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) + p := asIntFromType(field.Type(), param) return field.Int() == p @@ -1885,7 +1885,7 @@ func isLte(fl FieldLevel) bool { return int64(field.Len()) <= p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) + p := asIntFromType(field.Type(), param) return field.Int() <= p @@ -1932,7 +1932,7 @@ func isLt(fl FieldLevel) bool { return int64(field.Len()) < p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p := asInt(param) + p := asIntFromType(field.Type(), param) return field.Int() < p @@ -2205,11 +2205,8 @@ func isDatetime(fl FieldLevel) bool { if field.Kind() == reflect.String { _, err := time.Parse(param, field.String()) - if err != nil { - return false - } - return true + return err == nil } panic(fmt.Sprintf("Bad field type %T", field.Interface())) diff --git a/doc.go b/doc.go index 85527e99..d4d0186e 100644 --- a/doc.go +++ b/doc.go @@ -355,8 +355,17 @@ equal to the parameter given. For strings, it checks that the string length is exactly that number of characters. For slices, arrays, and maps, validates the number of items. +Example #1 + Usage: len=10 +Example #2 (time.Duration) + +For time.Duration, len will ensure that the value is equal to the duration given +in the parameter. + + Usage: len=1h30m + Maximum For numbers, max will ensure that the value is @@ -364,8 +373,17 @@ less than or equal to the parameter given. For strings, it checks that the string length is at most that number of characters. For slices, arrays, and maps, validates the number of items. +Example #1 + Usage: max=10 +Example #2 (time.Duration) + +For time.Duration, max will ensure that the value is less than or equal to the +duration given in the parameter. + + Usage: max=1h30m + Minimum For numbers, min will ensure that the value is @@ -373,24 +391,51 @@ greater or equal to the parameter given. For strings, it checks that the string length is at least that number of characters. For slices, arrays, and maps, validates the number of items. +Example #1 + Usage: min=10 +Example #2 (time.Duration) + +For time.Duration, min will ensure that the value is greater than or equal to +the duration given in the parameter. + + Usage: min=1h30m + Equals For strings & numbers, eq will ensure that the value is equal to the parameter given. For slices, arrays, and maps, validates the number of items. +Example #1 + Usage: eq=10 +Example #2 (time.Duration) + +For time.Duration, eq will ensure that the value is equal to the duration given +in the parameter. + + Usage: eq=1h30m + Not Equal For strings & numbers, ne will ensure that the value is not equal to the parameter given. For slices, arrays, and maps, validates the number of items. +Example #1 + Usage: ne=10 +Example #2 (time.Duration) + +For time.Duration, ne will ensure that the value is not equal to the duration +given in the parameter. + + Usage: ne=1h30m + One Of For strings, ints, and uints, oneof will ensure that the value @@ -420,11 +465,17 @@ For time.Time ensures the time value is greater than time.Now.UTC(). Usage: gt +Example #3 (time.Duration) + +For time.Duration, gt will ensure that the value is greater than the duration +given in the parameter. + + Usage: gt=1h30m + Greater Than or Equal Same as 'min' above. Kept both to make terminology with 'len' easier. - Example #1 Usage: gte=10 @@ -435,6 +486,13 @@ For time.Time ensures the time value is greater than or equal to time.Now.UTC(). Usage: gte +Example #3 (time.Duration) + +For time.Duration, gte will ensure that the value is greater than or equal to +the duration given in the parameter. + + Usage: gte=1h30m + Less Than For numbers, this will ensure that the value is less than the parameter given. @@ -446,10 +504,18 @@ Example #1 Usage: lt=10 Example #2 (time.Time) + For time.Time ensures the time value is less than time.Now.UTC(). Usage: lt +Example #3 (time.Duration) + +For time.Duration, lt will ensure that the value is less than the duration given +in the parameter. + + Usage: lt=1h30m + Less Than or Equal Same as 'max' above. Kept both to make terminology with 'len' easier. @@ -464,6 +530,13 @@ For time.Time ensures the time value is less than or equal to time.Now.UTC(). Usage: lte +Example #3 (time.Duration) + +For time.Duration, lte will ensure that the value is less than or equal to the +duration given in the parameter. + + Usage: lte=1h30m + Field Equals Another Field This will validate the field value against another fields value either within @@ -510,9 +583,9 @@ relative to the top level struct. Field Greater Than Another Field -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: +Only valid for Numbers, time.Duration and time.Time types, this will validate +the field value against another fields value either within a struct or passed in +field. usage examples are for validation of a Start and End date: Example #1: @@ -524,7 +597,6 @@ Example #2: // Validating by field: validate.VarWithValue(start, end, "gtfield") - Field Greater Than Another Relative Field This does the same as gtfield except that it validates the field provided @@ -534,9 +606,9 @@ relative to the top level struct. Field Greater Than or Equal To Another Field -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: +Only valid for Numbers, time.Duration and time.Time types, this will validate +the field value against another fields value either within a struct or passed in +field. usage examples are for validation of a Start and End date: Example #1: @@ -557,9 +629,9 @@ to the top level struct. Less Than Another Field -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: +Only valid for Numbers, time.Duration and time.Time types, this will validate +the field value against another fields value either within a struct or passed in +field. usage examples are for validation of a Start and End date: Example #1: @@ -580,9 +652,9 @@ to the top level struct. Less Than or Equal To Another Field -Only valid for Numbers and time.Time types, this will validate the field value -against another fields value either within a struct or passed in field. -usage examples are for validation of a Start and End date: +Only valid for Numbers, time.Duration and time.Time types, this will validate +the field value against another fields value either within a struct or passed in +field. usage examples are for validation of a Start and End date: Example #1: diff --git a/util.go b/util.go index 0d3a1810..6e568f83 100644 --- a/util.go +++ b/util.go @@ -4,6 +4,7 @@ import ( "reflect" "strconv" "strings" + "time" ) // extractTypeInternal gets the actual underlying type of field value. @@ -229,6 +230,26 @@ func asInt(param string) int64 { return i } +// asIntFromTimeDuration parses param as time.Duration and returns it as int64 +// or panics on error. +func asIntFromTimeDuration(param string) int64 { + d, err := time.ParseDuration(param) + panicIf(err) + + return int64(d) +} + +// asIntFromType calls the proper function to parse param as int64, +// given a field's Type t. +func asIntFromType(t reflect.Type, param string) int64 { + switch t { + case timeDurationType: + return asIntFromTimeDuration(param) + default: + return asInt(param) + } +} + // asUint returns the parameter as a uint64 // or panics if it can't convert func asUint(param string) uint64 { diff --git a/validator_instance.go b/validator_instance.go index 74acec03..fe6a4877 100644 --- a/validator_instance.go +++ b/validator_instance.go @@ -43,7 +43,9 @@ const ( ) var ( - timeType = reflect.TypeOf(time.Time{}) + timeDurationType = reflect.TypeOf(time.Duration(0)) + timeType = reflect.TypeOf(time.Time{}) + defaultCField = &cField{namesEqual: true} ) diff --git a/validator_test.go b/validator_test.go index 05b28c5e..0e1e9f70 100644 --- a/validator_test.go +++ b/validator_test.go @@ -952,6 +952,8 @@ func TestStructPartial(t *testing.T) { } func TestCrossStructLteFieldValidation(t *testing.T) { + var errs error + validate := New() type Inner struct { CreatedAt *time.Time @@ -994,8 +996,7 @@ func TestCrossStructLteFieldValidation(t *testing.T) { Array: []string{"val1"}, } - validate := New() - errs := validate.Struct(test) + errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then @@ -1058,9 +1059,68 @@ func TestCrossStructLteFieldValidation(t *testing.T) { errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltecsfield") + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltecsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "ltecsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltecsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltecsfield") + + errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltecsfield") + Equal(t, errs, nil) + + // -- Validations for a struct and an inner struct with time.Duration type fields. + + type TimeDurationInner struct { + Duration time.Duration + } + var timeDurationInner *TimeDurationInner + + type TimeDurationTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"ltecsfield=Inner.Duration"` + } + var timeDurationTest *TimeDurationTest + + timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltecsfield") + + type TimeDurationOmitemptyTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"omitempty,ltecsfield=Inner.Duration"` + } + var timeDurationOmitemptyTest *TimeDurationOmitemptyTest + + timeDurationInner = &TimeDurationInner{-time.Minute} + timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestCrossStructLtFieldValidation(t *testing.T) { + var errs error + validate := New() type Inner struct { CreatedAt *time.Time @@ -1103,8 +1163,7 @@ func TestCrossStructLtFieldValidation(t *testing.T) { Array: []string{"val1"}, } - validate := New() - errs := validate.Struct(test) + errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then @@ -1154,9 +1213,70 @@ func TestCrossStructLtFieldValidation(t *testing.T) { errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "ltcsfield") + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltcsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "ltcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltcsfield") + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltcsfield") + + errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltcsfield") + Equal(t, errs, nil) + + // -- Validations for a struct and an inner struct with time.Duration type fields. + + type TimeDurationInner struct { + Duration time.Duration + } + var timeDurationInner *TimeDurationInner + + type TimeDurationTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"ltcsfield=Inner.Duration"` + } + var timeDurationTest *TimeDurationTest + + timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield") + + timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ltcsfield") + + type TimeDurationOmitemptyTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"omitempty,ltcsfield=Inner.Duration"` + } + var timeDurationOmitemptyTest *TimeDurationOmitemptyTest + + timeDurationInner = &TimeDurationInner{-time.Minute} + timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestCrossStructGteFieldValidation(t *testing.T) { + var errs error + validate := New() type Inner struct { CreatedAt *time.Time @@ -1199,8 +1319,7 @@ func TestCrossStructGteFieldValidation(t *testing.T) { Array: []string{"val1", "val2", "val3"}, } - validate := New() - errs := validate.Struct(test) + errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then @@ -1262,9 +1381,68 @@ func TestCrossStructGteFieldValidation(t *testing.T) { errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtecsfield") + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtecsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "gtecsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtecsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gtecsfield") + + errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtecsfield") + Equal(t, errs, nil) + + // -- Validations for a struct and an inner struct with time.Duration type fields. + + type TimeDurationInner struct { + Duration time.Duration + } + var timeDurationInner *TimeDurationInner + + type TimeDurationTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"gtecsfield=Inner.Duration"` + } + var timeDurationTest *TimeDurationTest + + timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtecsfield") + + type TimeDurationOmitemptyTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"omitempty,gtecsfield=Inner.Duration"` + } + var timeDurationOmitemptyTest *TimeDurationOmitemptyTest + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestCrossStructGtFieldValidation(t *testing.T) { + var errs error + validate := New() type Inner struct { CreatedAt *time.Time @@ -1307,8 +1485,7 @@ func TestCrossStructGtFieldValidation(t *testing.T) { Array: []string{"val1", "val2", "val3"}, } - validate := New() - errs := validate.Struct(test) + errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then @@ -1358,9 +1535,70 @@ func TestCrossStructGtFieldValidation(t *testing.T) { errs = validate.Struct(tst) NotEqual(t, errs, nil) AssertError(t, errs, "Test2.Time", "Test2.Time", "Time", "Time", "gtcsfield") + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtcsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "gtcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gtcsfield") + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gtcsfield") + + errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtcsfield") + Equal(t, errs, nil) + + // -- Validations for a struct and an inner struct with time.Duration type fields. + + type TimeDurationInner struct { + Duration time.Duration + } + var timeDurationInner *TimeDurationInner + + type TimeDurationTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"gtcsfield=Inner.Duration"` + } + var timeDurationTest *TimeDurationTest + + timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield") + + timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gtcsfield") + + type TimeDurationOmitemptyTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"omitempty,gtcsfield=Inner.Duration"` + } + var timeDurationOmitemptyTest *TimeDurationOmitemptyTest + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestCrossStructNeFieldValidation(t *testing.T) { + var errs error + validate := New() type Inner struct { CreatedAt *time.Time @@ -1383,8 +1621,7 @@ func TestCrossStructNeFieldValidation(t *testing.T) { CreatedAt: &now, } - validate := New() - errs := validate.Struct(test) + errs = validate.Struct(test) Equal(t, errs, nil) test.CreatedAt = &then @@ -1466,9 +1703,68 @@ func TestCrossStructNeFieldValidation(t *testing.T) { errs = validate.VarWithValue(nil, 1, "necsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "necsfield") + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "necsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "necsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "necsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "necsfield") + + errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,necsfield") + Equal(t, errs, nil) + + // -- Validations for a struct and an inner struct with time.Duration type fields. + + type TimeDurationInner struct { + Duration time.Duration + } + var timeDurationInner *TimeDurationInner + + type TimeDurationTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"necsfield=Inner.Duration"` + } + var timeDurationTest *TimeDurationTest + + timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "necsfield") + + type TimeDurationOmitemptyTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"omitempty,necsfield=Inner.Duration"` + } + var timeDurationOmitemptyTest *TimeDurationOmitemptyTest + + timeDurationInner = &TimeDurationInner{time.Duration(0)} + timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestCrossStructEqFieldValidation(t *testing.T) { + var errs error + validate := New() type Inner struct { CreatedAt *time.Time @@ -1490,8 +1786,7 @@ func TestCrossStructEqFieldValidation(t *testing.T) { CreatedAt: &now, } - validate := New() - errs := validate.Struct(test) + errs = validate.Struct(test) Equal(t, errs, nil) newTime := time.Now().UTC() @@ -1571,6 +1866,65 @@ func TestCrossStructEqFieldValidation(t *testing.T) { errs = validate.VarWithValue(nil, 1, "eqcsfield") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "eqcsfield") + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour, "eqcsfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eqcsfield") + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqcsfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eqcsfield") + + errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqcsfield") + Equal(t, errs, nil) + + // -- Validations for a struct and an inner struct with time.Duration type fields. + + type TimeDurationInner struct { + Duration time.Duration + } + var timeDurationInner *TimeDurationInner + + type TimeDurationTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"eqcsfield=Inner.Duration"` + } + var timeDurationTest *TimeDurationTest + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationInner = &TimeDurationInner{time.Hour - time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield") + + timeDurationInner = &TimeDurationInner{time.Hour + time.Minute} + timeDurationTest = &TimeDurationTest{timeDurationInner, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eqcsfield") + + type TimeDurationOmitemptyTest struct { + Inner *TimeDurationInner + Duration time.Duration `validate:"omitempty,eqcsfield=Inner.Duration"` + } + var timeDurationOmitemptyTest *TimeDurationOmitemptyTest + + timeDurationInner = &TimeDurationInner{time.Hour} + timeDurationOmitemptyTest = &TimeDurationOmitemptyTest{timeDurationInner, time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestCrossNamespaceFieldValidation(t *testing.T) { @@ -4194,7 +4548,7 @@ func TestContainsValidation(t *testing.T) { } func TestIsNeFieldValidation(t *testing.T) { - + var errs error validate := New() var j uint64 @@ -4216,7 +4570,7 @@ func TestIsNeFieldValidation(t *testing.T) { arr3 := []string{"test"} now2 := now - errs := validate.VarWithValue(s, s2, "nefield") + errs = validate.VarWithValue(s, s2, "nefield") Equal(t, errs, nil) errs = validate.VarWithValue(i2, i, "nefield") @@ -4299,10 +4653,57 @@ func TestIsNeFieldValidation(t *testing.T) { errs = validate.Struct(tst) Equal(t, errs, nil) + + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "nefield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "nefield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "nefield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "nefield") + + errs = validate.VarWithValue(time.Duration(0), time.Duration(0), "omitempty,nefield") + Equal(t, errs, nil) + + // -- Validations for a struct with time.Duration type fields. + + type TimeDurationTest struct { + First time.Duration `validate:"nefield=Second"` + Second time.Duration + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "nefield") + + type TimeDurationOmitemptyTest struct { + First time.Duration `validate:"omitempty,nefield=Second"` + Second time.Duration + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestIsNeValidation(t *testing.T) { - + var errs error validate := New() var j uint64 @@ -4314,7 +4715,7 @@ func TestIsNeValidation(t *testing.T) { arr := []string{"test"} now := time.Now().UTC() - errs := validate.Var(s, "ne=abcd") + errs = validate.Var(s, "ne=abcd") Equal(t, errs, nil) errs = validate.Var(i, "ne=1") @@ -4334,10 +4735,55 @@ func TestIsNeValidation(t *testing.T) { AssertError(t, errs, "", "", "", "", "ne") PanicMatches(t, func() { _ = validate.Var(now, "ne=now") }, "Bad field type time.Time") + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour-time.Minute, "ne=1h") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+time.Minute, "ne=1h") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour, "ne=1h") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ne") + + errs = validate.Var(time.Duration(0), "omitempty,ne=0") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"ne=1h"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "ne") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,ne=0"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestIsEqFieldValidation(t *testing.T) { - + var errs error validate := New() var j uint64 @@ -4359,7 +4805,7 @@ func TestIsEqFieldValidation(t *testing.T) { arr3 := []string{"test", "test2"} now2 := now - errs := validate.VarWithValue(s, s2, "eqfield") + errs = validate.VarWithValue(s, s2, "eqfield") Equal(t, errs, nil) errs = validate.VarWithValue(i2, i, "eqfield") @@ -4453,34 +4899,83 @@ func TestIsEqFieldValidation(t *testing.T) { errs = validate.Struct(test) NotEqual(t, errs, nil) AssertError(t, errs, "TStruct.CreatedAt", "TStruct.CreatedAt", "CreatedAt", "CreatedAt", "eqfield") -} - -func TestIsEqValidation(t *testing.T) { - validate := New() + // Tests for time.Duration type. - var j uint64 - var k float64 - s := "abcd" - i := 1 - j = 1 - k = 1.543 - arr := []string{"test"} - now := time.Now().UTC() + // -- Validations for variables of time.Duration type. - errs := validate.Var(s, "eq=abcd") + errs = validate.VarWithValue(time.Hour, time.Hour, "eqfield") Equal(t, errs, nil) - errs = validate.Var(i, "eq=1") - Equal(t, errs, nil) + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "eqfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eqfield") - errs = validate.Var(j, "eq=1") - Equal(t, errs, nil) + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "eqfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eqfield") - errs = validate.Var(k, "eq=1.543") + errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,eqfield") Equal(t, errs, nil) - errs = validate.Var(arr, "eq=1") + // -- Validations for a struct with time.Duration type fields. + + type TimeDurationTest struct { + First time.Duration `validate:"eqfield=Second"` + Second time.Duration + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield") + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "eqfield") + + type TimeDurationOmitemptyTest struct { + First time.Duration `validate:"omitempty,eqfield=Second"` + Second time.Duration + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) +} + +func TestIsEqValidation(t *testing.T) { + var errs error + validate := New() + + var j uint64 + var k float64 + s := "abcd" + i := 1 + j = 1 + k = 1.543 + arr := []string{"test"} + now := time.Now().UTC() + + errs = validate.Var(s, "eq=abcd") + Equal(t, errs, nil) + + errs = validate.Var(i, "eq=1") + Equal(t, errs, nil) + + errs = validate.Var(j, "eq=1") + Equal(t, errs, nil) + + errs = validate.Var(k, "eq=1.543") + Equal(t, errs, nil) + + errs = validate.Var(arr, "eq=1") Equal(t, errs, nil) errs = validate.Var(arr, "eq=2") @@ -4488,6 +4983,53 @@ func TestIsEqValidation(t *testing.T) { AssertError(t, errs, "", "", "", "", "eq") PanicMatches(t, func() { _ = validate.Var(now, "eq=now") }, "Bad field type time.Time") + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "eq=1h") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-time.Minute, "eq=1h") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eq") + + errs = validate.Var(time.Hour+time.Minute, "eq=1h") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "eq") + + errs = validate.Var(time.Duration(0), "omitempty,eq=1h") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"eq=1h"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq") + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "eq") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,eq=1h"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestOneOfValidation(t *testing.T) { @@ -4964,7 +5506,7 @@ func TestStructOnlyValidation(t *testing.T) { } func TestGtField(t *testing.T) { - + var errs error validate := New() type TimeTest struct { @@ -4981,7 +5523,7 @@ func TestGtField(t *testing.T) { End: &end, } - errs := validate.Struct(timeTest) + errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ @@ -5009,6 +5551,57 @@ func TestGtField(t *testing.T) { errs = validate.VarWithValue("test bigger", "test", "gtfield") Equal(t, errs, nil) + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "gtfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gtfield") + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gtfield") + + errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtfield") + Equal(t, errs, nil) + + // -- Validations for a struct with time.Duration type fields. + + type TimeDurationTest struct { + First time.Duration `validate:"gtfield=Second"` + Second time.Duration + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield") + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtfield") + + type TimeDurationOmitemptyTest struct { + First time.Duration `validate:"omitempty,gtfield=Second"` + Second time.Duration + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) + + // Tests for Ints types. + type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,gtfield=Val1"` @@ -5142,7 +5735,7 @@ func TestGtField(t *testing.T) { } func TestLtField(t *testing.T) { - + var errs error validate := New() type TimeTest struct { @@ -5159,7 +5752,7 @@ func TestLtField(t *testing.T) { End: &end, } - errs := validate.Struct(timeTest) + errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ @@ -5185,6 +5778,57 @@ func TestLtField(t *testing.T) { errs = validate.VarWithValue("tes", "test", "ltfield") Equal(t, errs, nil) + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltfield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "ltfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltfield") + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltfield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltfield") + + errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltfield") + Equal(t, errs, nil) + + // -- Validations for a struct with time.Duration type fields. + + type TimeDurationTest struct { + First time.Duration `validate:"ltfield=Second"` + Second time.Duration + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield") + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltfield") + + type TimeDurationOmitemptyTest struct { + First time.Duration `validate:"omitempty,ltfield=Second"` + Second time.Duration + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) + + // Tests for Ints types. + type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,ltfield=Val1"` @@ -5423,7 +6067,7 @@ func TestContainsAndExcludes(t *testing.T) { } func TestLteField(t *testing.T) { - + var errs error validate := New() type TimeTest struct { @@ -5440,7 +6084,7 @@ func TestLteField(t *testing.T) { End: &end, } - errs := validate.Struct(timeTest) + errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ @@ -5469,6 +6113,55 @@ func TestLteField(t *testing.T) { errs = validate.VarWithValue("test", "test", "ltefield") Equal(t, errs, nil) + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "ltefield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "ltefield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "ltefield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "ltefield") + + errs = validate.VarWithValue(time.Duration(0), -time.Minute, "omitempty,ltefield") + Equal(t, errs, nil) + + // -- Validations for a struct with time.Duration type fields. + + type TimeDurationTest struct { + First time.Duration `validate:"ltefield=Second"` + Second time.Duration + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "ltefield") + + type TimeDurationOmitemptyTest struct { + First time.Duration `validate:"omitempty,ltefield=Second"` + Second time.Duration + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), -time.Minute} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) + + // Tests for Ints types. + type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,ltefield=Val1"` @@ -5584,7 +6277,7 @@ func TestLteField(t *testing.T) { } func TestGteField(t *testing.T) { - + var errs error validate := New() type TimeTest struct { @@ -5601,7 +6294,7 @@ func TestGteField(t *testing.T) { End: &end, } - errs := validate.Struct(timeTest) + errs = validate.Struct(timeTest) Equal(t, errs, nil) timeTest = &TimeTest{ @@ -5630,6 +6323,55 @@ func TestGteField(t *testing.T) { errs = validate.VarWithValue("test bigger", "test", "gtefield") Equal(t, errs, nil) + // Tests for time.Duration type. + + // -- Validations for variables of time.Duration type. + + errs = validate.VarWithValue(time.Hour, time.Hour-time.Minute, "gtefield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour, "gtefield") + Equal(t, errs, nil) + + errs = validate.VarWithValue(time.Hour, time.Hour+time.Minute, "gtefield") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gtefield") + + errs = validate.VarWithValue(time.Duration(0), time.Hour, "omitempty,gtefield") + Equal(t, errs, nil) + + // -- Validations for a struct with time.Duration type fields. + + type TimeDurationTest struct { + First time.Duration `validate:"gtefield=Second"` + Second time.Duration + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour, time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.First", "TimeDurationTest.First", "First", "First", "gtefield") + + type TimeDurationOmitemptyTest struct { + First time.Duration `validate:"omitempty,gtefield=Second"` + Second time.Duration + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0), time.Hour} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) + + // Tests for Ints types. + type IntTest struct { Val1 int `validate:"required"` Val2 int `validate:"required,gtefield=Val1"` @@ -5865,9 +6607,11 @@ func TestLength(t *testing.T) { } func TestIsGt(t *testing.T) { + var errs error validate := New() + myMap := map[string]string{} - errs := validate.Var(myMap, "gt=0") + errs = validate.Var(myMap, "gt=0") NotEqual(t, errs, nil) f := 1.23 @@ -5912,17 +6656,66 @@ func TestIsGt(t *testing.T) { errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gt") + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "gt=59m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-time.Minute, "gt=59m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gt") + + errs = validate.Var(time.Hour-2*time.Minute, "gt=59m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gt") + + errs = validate.Var(time.Duration(0), "omitempty,gt=59m") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"gt=59m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt") + + timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gt") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,gt=59m"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestIsGte(t *testing.T) { + var errs error validate := New() + i := true PanicMatches(t, func() { _ = validate.Var(i, "gte") }, "Bad field type bool") t1 := time.Now().UTC() t1 = t1.Add(time.Hour * 24) - errs := validate.Var(t1, "gte") + errs = validate.Var(t1, "gte") Equal(t, errs, nil) t2 := time.Now().UTC().Add(-time.Hour) @@ -5948,12 +6741,277 @@ func TestIsGte(t *testing.T) { errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "gte") + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "gte=59m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-time.Minute, "gte=59m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-2*time.Minute, "gte=59m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "gte") + + errs = validate.Var(time.Duration(0), "omitempty,gte=59m") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"gte=59m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "gte") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,gte=59m"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) +} + +func TestMinValidation(t *testing.T) { + var errs error + validate := New() + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "min=59m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-time.Minute, "min=59m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-2*time.Minute, "min=59m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "min") + + errs = validate.Var(time.Duration(0), "omitempty,min=59m") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"min=59m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,min=59m"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) +} + +func TestMaxValidation(t *testing.T) { + var errs error + validate := New() + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "max=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+time.Minute, "max=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+2*time.Minute, "max=1h1m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "max") + + errs = validate.Var(time.Duration(0), "omitempty,max=-1s") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"max=1h1m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,max=-1s"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) +} + +func TestMinMaxValidation(t *testing.T) { + var errs error + validate := New() + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "min=59m,max=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-time.Minute, "min=59m,max=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+time.Minute, "min=59m,max=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-2*time.Minute, "min=59m,max=1h1m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "min") + + errs = validate.Var(time.Hour+2*time.Minute, "min=59m,max=1h1m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "max") + + errs = validate.Var(time.Duration(0), "omitempty,min=59m,max=1h1m") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"min=59m,max=1h1m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "min") + + timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "max") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,min=59m,max=1h1m"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) +} + +func TestLenValidation(t *testing.T) { + var errs error + validate := New() + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "len=1h") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour-time.Minute, "len=1h") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "len") + + errs = validate.Var(time.Hour+time.Minute, "len=1h") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "len") + + errs = validate.Var(time.Duration(0), "omitempty,len=1h") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"len=1h"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour - time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len") + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "len") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,len=1h"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestIsLt(t *testing.T) { + var errs error validate := New() + myMap := map[string]string{} - errs := validate.Var(myMap, "lt=0") + errs = validate.Var(myMap, "lt=0") NotEqual(t, errs, nil) AssertError(t, errs, "", "", "", "", "lt") @@ -6000,10 +7058,57 @@ func TestIsLt(t *testing.T) { errs = validate.Struct(s) NotEqual(t, errs, nil) AssertError(t, errs, "Test.Now", "Test.Now", "Now", "Now", "lt") + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "lt=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+time.Minute, "lt=1h1m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "lt") + + errs = validate.Var(time.Hour+2*time.Minute, "lt=1h1m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "lt") + + errs = validate.Var(time.Duration(0), "omitempty,lt=0") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"lt=1h1m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt") + + timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lt") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,lt=0"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestIsLte(t *testing.T) { - + var errs error validate := New() i := true @@ -6011,7 +7116,7 @@ func TestIsLte(t *testing.T) { t1 := time.Now().UTC().Add(-time.Hour) - errs := validate.Var(t1, "lte") + errs = validate.Var(t1, "lte") Equal(t, errs, nil) t2 := time.Now().UTC() @@ -6038,6 +7143,51 @@ func TestIsLte(t *testing.T) { errs = validate.Struct(s) NotEqual(t, errs, nil) + + // Tests for time.Duration type. + + // -- Validations for a variable of time.Duration type. + + errs = validate.Var(time.Hour, "lte=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+time.Minute, "lte=1h1m") + Equal(t, errs, nil) + + errs = validate.Var(time.Hour+2*time.Minute, "lte=1h1m") + NotEqual(t, errs, nil) + AssertError(t, errs, "", "", "", "", "lte") + + errs = validate.Var(time.Duration(0), "omitempty,lte=-1s") + Equal(t, errs, nil) + + // -- Validations for a struct with a time.Duration type field. + + type TimeDurationTest struct { + Duration time.Duration `validate:"lte=1h1m"` + } + var timeDurationTest *TimeDurationTest + + timeDurationTest = &TimeDurationTest{time.Hour} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + time.Minute} + errs = validate.Struct(timeDurationTest) + Equal(t, errs, nil) + + timeDurationTest = &TimeDurationTest{time.Hour + 2*time.Minute} + errs = validate.Struct(timeDurationTest) + NotEqual(t, errs, nil) + AssertError(t, errs, "TimeDurationTest.Duration", "TimeDurationTest.Duration", "Duration", "Duration", "lte") + + type TimeDurationOmitemptyTest struct { + Duration time.Duration `validate:"omitempty,lte=-1s"` + } + + timeDurationOmitemptyTest := &TimeDurationOmitemptyTest{time.Duration(0)} + errs = validate.Struct(timeDurationOmitemptyTest) + Equal(t, errs, nil) } func TestUrnRFC2141(t *testing.T) { @@ -8256,7 +9406,7 @@ func TestUniqueValidationStructSlice(t *testing.T) { } } } - PanicMatches(t, func() { validate.Var(testStructs, "unique=C") }, "Bad field name C") + PanicMatches(t, func() { _ = validate.Var(testStructs, "unique=C") }, "Bad field name C") } func TestUniqueValidationStructPtrSlice(t *testing.T) { @@ -9484,7 +10634,7 @@ func TestGetTag(t *testing.T) { } val := New() - val.RegisterValidation("mytag", func(fl FieldLevel) bool { + _ = val.RegisterValidation("mytag", func(fl FieldLevel) bool { tag = fl.GetTag() return true })