diff --git a/null_handlers.go b/null_handlers.go new file mode 100644 index 0000000..5156bd2 --- /dev/null +++ b/null_handlers.go @@ -0,0 +1,71 @@ +package validator + +import ( + "errors" + "gopkg.in/guregu/null.v3" + "strconv" + "time" +) + +func NullIntHandler(input string, value *Value) error { + // Get int64 + res, err := strconv.ParseInt(input, 10, 64) + if err != nil { + return errors.New(invalidParam(value.Name, "an int64")) + } + + // Update null.Int + nullInt := value.Result.(*null.Int) + (*nullInt).Int64 = int64(res) + (*nullInt).Valid = true + return nil +} + +func NullStringHandler(input string, value *Value) error { + nullString := value.Result.(*null.String) + (*nullString).String = input + (*nullString).Valid = true + return nil +} + +func NullFloatHandler(input string, value *Value) error { + // Get float64 + res, err := strconv.ParseFloat(input, 64) + if err != nil { + return errors.New(invalidParam(value.Name, "a float64")) + } + + // Update null.Float + nullFloat := value.Result.(*null.Float) + (*nullFloat).Float64 = res + (*nullFloat).Valid = true + return nil +} + +func NullBoolHandler(input string, value *Value) error { + // Get bool + res, err := strconv.ParseBool(input) + if err != nil { + return errors.New(invalidParam(value.Name, "a bool")) + } + + // Update null.Bool + nullBool := value.Result.(*null.Bool) + (*nullBool).Bool = res + (*nullBool).Valid = true + return nil +} + +func NullTimeHandler(input string, value *Value) error { + // Get time.Time + res, err := time.Parse(time.RFC3339, input) + if err != nil { + return errors.New(invalidParam(value.Name, "an RFC 3339 date-time (2006-01-02T15:04:05Z07:00)")) + } + + // Update null.Time + nullTime := value.Result.(*null.Time) + (*nullTime).Time = res + (*nullTime).Valid = true + return nil +} diff --git a/null_handlers_test.go b/null_handlers_test.go new file mode 100644 index 0000000..aa65b1e --- /dev/null +++ b/null_handlers_test.go @@ -0,0 +1,101 @@ +package validator_test + +import ( + v "github.com/go-carrot/validator" + "github.com/stretchr/testify/assert" + "gopkg.in/guregu/null.v3" + "testing" + "time" +) + +// TestNullInt tests handling of a null.Int as the result +func TestNullInt(t *testing.T) { + // Test success case + var id null.Int + err := v.Validate([]*v.Value{ + {Result: &id, Name: "id", Input: "12", TypeHandler: v.NullIntHandler}, + }) + assert.Nil(t, err) + assert.Equal(t, int64(12), id.Int64) + assert.True(t, id.Valid) + + // Test failure case + var failureId null.Int + err = v.Validate([]*v.Value{ + {Result: &failureId, Name: "id", Input: "12a", TypeHandler: v.NullIntHandler}, + }) + assert.NotNil(t, err) + assert.False(t, failureId.Valid) +} + +// TestNullString tests handling of a null.String as the result +func TestNullString(t *testing.T) { + // Test success case + var slug null.String + err := v.Validate([]*v.Value{ + {Result: &slug, Name: "slug", Input: "hello", TypeHandler: v.NullStringHandler}, + }) + assert.Nil(t, err) + assert.Equal(t, "hello", slug.String) + assert.True(t, slug.Valid) +} + +// TestNullFloat tests handling of a null.Float as the result +func TestNullFloat(t *testing.T) { + // Test success case + var id null.Float + err := v.Validate([]*v.Value{ + {Result: &id, Name: "id", Input: "12.8", TypeHandler: v.NullFloatHandler}, + }) + assert.Nil(t, err) + assert.Equal(t, float64(12.8), id.Float64) + assert.True(t, id.Valid) + + // Test failure case + var failureId null.Float + err = v.Validate([]*v.Value{ + {Result: &failureId, Name: "id", Input: "12.8a", TypeHandler: v.NullFloatHandler}, + }) + assert.NotNil(t, err) + assert.False(t, failureId.Valid) +} + +// TestNullBool tests handling of a null.Bool as the result +func TestNullBool(t *testing.T) { + // Test success case + var someBool null.Bool + err := v.Validate([]*v.Value{ + {Result: &someBool, Name: "some_bool", Input: "true", TypeHandler: v.NullBoolHandler}, + }) + assert.Nil(t, err) + assert.True(t, someBool.Bool) + assert.True(t, someBool.Valid) + + // Test failure case + var someOtherBool null.Bool + err = v.Validate([]*v.Value{ + {Result: &someOtherBool, Name: "some_other_bool", Input: "12.8a", TypeHandler: v.NullBoolHandler}, + }) + assert.NotNil(t, err) + assert.False(t, someOtherBool.Valid) +} + +// TestNullTime tests handling of a null.Time as the result +func TestNullTime(t *testing.T) { + // Test success case + var successTime null.Time + err := v.Validate([]*v.Value{ + {Result: &successTime, Name: "time", Input: "2012-11-01T22:08:41+00:00", TypeHandler: v.NullTimeHandler}, + }) + assert.Nil(t, err) + assert.Equal(t, successTime.Time.Year(), 2012) + assert.Equal(t, successTime.Time.Month(), time.November) + assert.Equal(t, successTime.Time.Day(), 1) + + // Test failure case + var errorTime time.Time + err = v.Validate([]*v.Value{ + {Result: &errorTime, Name: "time", Input: "abcd", TypeHandler: v.NullTimeHandler}, + }) + assert.NotNil(t, err) +} diff --git a/type_handlers.go b/primitive_handlers.go similarity index 92% rename from type_handlers.go rename to primitive_handlers.go index 03b8f76..fae8b3f 100644 --- a/type_handlers.go +++ b/primitive_handlers.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strconv" + "time" ) func stringHandler(input string, value *Value) error { @@ -128,6 +129,15 @@ func uint64Handler(input string, value *Value) error { return nil } +func timeHandler(input string, value *Value) error { + res, err := time.Parse(time.RFC3339, input) + if err != nil { + return errors.New(invalidParam(value.Name, "an RFC 3339 date-time (2006-01-02T15:04:05Z07:00)")) + } + *value.Result.(*time.Time) = res + return nil +} + func invalidParam(name string, mustBe string) string { return fmt.Sprintf("Invalid `%v` parameter, `%v` must be %v", name, name, mustBe) } diff --git a/primitive_handlers_test.go b/primitive_handlers_test.go new file mode 100644 index 0000000..2749615 --- /dev/null +++ b/primitive_handlers_test.go @@ -0,0 +1,645 @@ +package validator_test + +import ( + v "github.com/go-carrot/validator" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +// TestString tests handling of a string as the result +func TestString(t *testing.T) { + // Test success case + var successId string + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, "20", successId) + + // Test empty case + var emptyId string + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, "", emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId string + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, "", emptyIsSetId) +} + +// TestFloat32 tests handing of a float32 as the result +func TestFloat32(t *testing.T) { + // Test success case + var successId float32 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20.2"}, + }) + assert.Nil(t, err) + assert.Equal(t, float32(20.2), successId) + + // Test another success case + var anotherSuccessId float32 + err = v.Validate([]*v.Value{ + {Result: &anotherSuccessId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, float32(20.0), anotherSuccessId) + + // Test empty case + var emptyId float32 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, float32(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId float32 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, float32(0), emptyIsSetId) + + // Test parse failure case + var parseFailureId float32 + err = v.Validate([]*v.Value{ + {Result: &parseFailureId, Name: "id", Input: "20a", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, float32(0), parseFailureId) +} + +// TestFloat64 tests handing of a float64 as the result +func TestFloat64(t *testing.T) { + // Test success case + var successId float64 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20.2"}, + }) + assert.Nil(t, err) + assert.Equal(t, float64(20.2), successId) + + // Test another success case + var anotherSuccessId float64 + err = v.Validate([]*v.Value{ + {Result: &anotherSuccessId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, float64(20.0), anotherSuccessId) + + // Test empty case + var emptyId float64 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, float64(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId float64 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, float64(0), emptyIsSetId) + + // Test parse failure case + var parseFailureId float64 + err = v.Validate([]*v.Value{ + {Result: &parseFailureId, Name: "id", Input: "20a", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, float64(0), parseFailureId) +} + +// TestBool tests handing of a bool as the result +func TestBool(t *testing.T) { + // Test success case + var successBool bool + err := v.Validate([]*v.Value{ + {Result: &successBool, Name: "bool", Input: "true"}, + }) + assert.Nil(t, err) + assert.Equal(t, true, successBool) + + // Test empty case + var emptyBool bool + err = v.Validate([]*v.Value{ + {Result: &emptyBool, Name: "bool", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, false, emptyBool) + + // Test empty case with IsSet rule + var emptyIsSetBool bool + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetBool, Name: "bool", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, false, emptyIsSetBool) + + // Test failure case + var failureBool bool + err = v.Validate([]*v.Value{ + {Result: &failureBool, Name: "bool", Input: "not-a-bool"}, + }) + assert.NotNil(t, err) + assert.Equal(t, false, failureBool) +} + +// TestInt tests handing of an int as the result +func TestInt(t *testing.T) { + // Test success case + var successId int + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, int(20), successId) + + // Test empty case + var emptyId int + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, int(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId int + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, int(0), emptyIsSetId) + + // Test overflow case + var overflowId int + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "9223372036854775808"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int(0), overflowId) + + // Test string case + var stringId int + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int(0), stringId) +} + +// TestInt8 tests handing of an int8 as the result +func TestInt8(t *testing.T) { + // Test success case + var successId int8 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, int8(20), successId) + + // Test empty case + var emptyId int8 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, int8(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId int8 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, int8(0), emptyIsSetId) + + // Test overflow case + var overflowId int8 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "128"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int8(0), overflowId) + + // Test string case + var stringId int8 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int8(0), stringId) +} + +// TestInt16 tests handing of an int16 as the result +func TestInt16(t *testing.T) { + // Test success case + var successId int16 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, int16(20), successId) + + // Test empty case + var emptyId int16 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, int16(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId int16 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, int16(0), emptyIsSetId) + + // Test overflow case + var overflowId int16 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "32768"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int16(0), overflowId) + + // Test string case + var stringId int16 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int16(0), stringId) +} + +// TestInt32 tests handling of an int32 as the result +func TestInt32(t *testing.T) { + // Test success case + var successId int32 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, int32(20), successId) + + // Test empty case + var emptyId int32 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, int32(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId int32 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, int32(0), emptyIsSetId) + + // Test successful case with MaxVal rule + var maxValPassId int32 + err = v.Validate([]*v.Value{ + {Result: &maxValPassId, Name: "id", Input: "100", Rules: []v.Rule{MaxVal(100)}}, + }) + assert.Nil(t, err) + assert.Equal(t, int32(100), maxValPassId) + + // Test failure case with MaxVal rule + var maxValFailureId int32 + err = v.Validate([]*v.Value{ + {Result: &maxValFailureId, Name: "id", Input: "101", Rules: []v.Rule{MaxVal(100)}}, + }) + assert.NotNil(t, err) + assert.Equal(t, int32(0), maxValFailureId) + + // Test string case + var stringId int32 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "hello world"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int32(0), stringId) + + // Test float case + var floatId int32 + err = v.Validate([]*v.Value{ + {Result: &floatId, Name: "id", Input: "20.1"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int32(0), floatId) + + // Test overflow case + var overflowId int32 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "2147483648"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int32(0), overflowId) +} + +// TestInt64 tests handing of an int64 as the result +func TestInt64(t *testing.T) { + // Test success case + var successId int64 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, int64(20), successId) + + // Test empty case + var emptyId int64 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, int64(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId int64 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, int64(0), emptyIsSetId) + + // Test overflow case + var overflowId int64 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "9223372036854775808"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int64(0), overflowId) + + // Test string case + var stringId int64 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, int64(0), stringId) +} + +// TestUint tests handing of a uint as the result +func TestUint(t *testing.T) { + // Test success case + var successId uint + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, uint(20), successId) + + // Test empty case + var emptyId uint + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, uint(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId uint + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint(0), emptyIsSetId) + + // Test overflow case + var overflowId uint + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "18446744073709551616"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint(0), overflowId) + + // Test string case + var stringId uint + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint(0), stringId) +} + +// TestUint8 tests handing of an uint8 as the result +func TestUint8(t *testing.T) { + // Test success case + var successId uint8 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, uint8(20), successId) + + // Test empty case + var emptyId uint8 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, uint8(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId uint8 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint8(0), emptyIsSetId) + + // Test overflow case + var overflowId uint8 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "256"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint8(0), overflowId) + + // Test string case + var stringId uint8 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint8(0), stringId) +} + +// TestUint16 tests handing of an uint16 as the result +func TestUint16(t *testing.T) { + // Test success case + var successId uint16 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, uint16(20), successId) + + // Test empty case + var emptyId uint16 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, uint16(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId uint16 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint16(0), emptyIsSetId) + + // Test overflow case + var overflowId uint16 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "65536"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint16(0), overflowId) + + // Test string case + var stringId uint16 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint16(0), stringId) +} + +// TestUint32 tests handing of an uint32 as the result +func TestUint32(t *testing.T) { + // Test success case + var successId uint32 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, uint32(20), successId) + + // Test empty case + var emptyId uint32 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, uint32(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId uint32 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint32(0), emptyIsSetId) + + // Test overflow case + var overflowId uint32 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "4294967296"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint32(0), overflowId) + + // Test string case + var stringId uint32 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint32(0), stringId) +} + +// TestUint64 tests handing of an uint64 as the result +func TestUint64(t *testing.T) { + // Test success case + var successId uint64 + err := v.Validate([]*v.Value{ + {Result: &successId, Name: "id", Input: "20"}, + }) + assert.Nil(t, err) + assert.Equal(t, uint64(20), successId) + + // Test empty case + var emptyId uint64 + err = v.Validate([]*v.Value{ + {Result: &emptyId, Name: "id", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, uint64(0), emptyId) + + // Test empty case with IsSet rule + var emptyIsSetId uint64 + err = v.Validate([]*v.Value{ + {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint64(0), emptyIsSetId) + + // Test overflow case + var overflowId uint64 + err = v.Validate([]*v.Value{ + {Result: &overflowId, Name: "id", Input: "18446744073709551616"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint64(0), overflowId) + + // Test string case + var stringId uint64 + err = v.Validate([]*v.Value{ + {Result: &stringId, Name: "id", Input: "Hello World"}, + }) + assert.NotNil(t, err) + assert.Equal(t, uint64(0), stringId) +} + +// TestTime tests handling of a time.Time as the result +func TestTime(t *testing.T) { + // Test success case + var successTime time.Time + err := v.Validate([]*v.Value{ + {Result: &successTime, Name: "time", Input: "2012-11-01T22:08:41+00:00"}, + }) + assert.Nil(t, err) + assert.Equal(t, successTime.Year(), 2012) + assert.Equal(t, successTime.Month(), time.November) + assert.Equal(t, successTime.Day(), 1) + + // Test empty case + var emptyTime time.Time + err = v.Validate([]*v.Value{ + {Result: &emptyTime, Name: "time", Input: ""}, + }) + assert.Nil(t, err) + assert.Equal(t, emptyTime.Year(), 1) + + // Test empty with isSet rule + err = v.Validate([]*v.Value{ + {Result: &emptyTime, Name: "time", Input: "", Rules: []v.Rule{IsSet}}, + }) + assert.NotNil(t, err) + assert.Equal(t, emptyTime.Year(), 1) + + // Test error case + var errorTime time.Time + err = v.Validate([]*v.Value{ + {Result: &errorTime, Name: "time", Input: "abcd"}, + }) + assert.NotNil(t, err) +} diff --git a/validator.go b/validator.go index 7fc73a6..a04c097 100644 --- a/validator.go +++ b/validator.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "reflect" + "time" ) // Value is the definition of a parameter that you would like to perform validation against. @@ -96,6 +97,8 @@ func applyTypeHandler(value *Value) error { value.TypeHandler = uint32Handler case *uint64: value.TypeHandler = uint64Handler + case *time.Time: + value.TypeHandler = timeHandler } return nil } diff --git a/validator_test.go b/validator_test.go index 034a70c..0add9bb 100644 --- a/validator_test.go +++ b/validator_test.go @@ -49,608 +49,6 @@ func TestUnknownType(t *testing.T) { assert.Fail(t, "Line of code should be unreachable") } -// TestString tests handling of a string as the result -func TestString(t *testing.T) { - // Test success case - var successId string - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, "20", successId) - - // Test empty case - var emptyId string - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, "", emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId string - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, "", emptyIsSetId) -} - -// TestFloat32 tests handing of a float32 as the result -func TestFloat32(t *testing.T) { - // Test success case - var successId float32 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20.2"}, - }) - assert.Nil(t, err) - assert.Equal(t, float32(20.2), successId) - - // Test another success case - var anotherSuccessId float32 - err = v.Validate([]*v.Value{ - {Result: &anotherSuccessId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, float32(20.0), anotherSuccessId) - - // Test empty case - var emptyId float32 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, float32(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId float32 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, float32(0), emptyIsSetId) - - // Test parse failure case - var parseFailureId float32 - err = v.Validate([]*v.Value{ - {Result: &parseFailureId, Name: "id", Input: "20a", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, float32(0), parseFailureId) -} - -// TestFloat64 tests handing of a float64 as the result -func TestFloat64(t *testing.T) { - // Test success case - var successId float64 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20.2"}, - }) - assert.Nil(t, err) - assert.Equal(t, float64(20.2), successId) - - // Test another success case - var anotherSuccessId float64 - err = v.Validate([]*v.Value{ - {Result: &anotherSuccessId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, float64(20.0), anotherSuccessId) - - // Test empty case - var emptyId float64 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, float64(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId float64 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, float64(0), emptyIsSetId) - - // Test parse failure case - var parseFailureId float64 - err = v.Validate([]*v.Value{ - {Result: &parseFailureId, Name: "id", Input: "20a", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, float64(0), parseFailureId) -} - -// TestBool tests handing of a bool as the result -func TestBool(t *testing.T) { - // Test success case - var successBool bool - err := v.Validate([]*v.Value{ - {Result: &successBool, Name: "bool", Input: "true"}, - }) - assert.Nil(t, err) - assert.Equal(t, true, successBool) - - // Test empty case - var emptyBool bool - err = v.Validate([]*v.Value{ - {Result: &emptyBool, Name: "bool", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, false, emptyBool) - - // Test empty case with IsSet rule - var emptyIsSetBool bool - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetBool, Name: "bool", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, false, emptyIsSetBool) - - // Test failure case - var failureBool bool - err = v.Validate([]*v.Value{ - {Result: &failureBool, Name: "bool", Input: "not-a-bool"}, - }) - assert.NotNil(t, err) - assert.Equal(t, false, failureBool) -} - -// TestInt tests handing of an int as the result -func TestInt(t *testing.T) { - // Test success case - var successId int - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, int(20), successId) - - // Test empty case - var emptyId int - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, int(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId int - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, int(0), emptyIsSetId) - - // Test overflow case - var overflowId int - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "9223372036854775808"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int(0), overflowId) - - // Test string case - var stringId int - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int(0), stringId) -} - -// TestInt8 tests handing of an int8 as the result -func TestInt8(t *testing.T) { - // Test success case - var successId int8 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, int8(20), successId) - - // Test empty case - var emptyId int8 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, int8(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId int8 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, int8(0), emptyIsSetId) - - // Test overflow case - var overflowId int8 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "128"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int8(0), overflowId) - - // Test string case - var stringId int8 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int8(0), stringId) -} - -// TestInt16 tests handing of an int16 as the result -func TestInt16(t *testing.T) { - // Test success case - var successId int16 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, int16(20), successId) - - // Test empty case - var emptyId int16 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, int16(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId int16 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, int16(0), emptyIsSetId) - - // Test overflow case - var overflowId int16 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "32768"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int16(0), overflowId) - - // Test string case - var stringId int16 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int16(0), stringId) -} - -// TestInt32 tests handling of an int32 as the result -func TestInt32(t *testing.T) { - // Test success case - var successId int32 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, int32(20), successId) - - // Test empty case - var emptyId int32 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, int32(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId int32 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, int32(0), emptyIsSetId) - - // Test successful case with MaxVal rule - var maxValPassId int32 - err = v.Validate([]*v.Value{ - {Result: &maxValPassId, Name: "id", Input: "100", Rules: []v.Rule{MaxVal(100)}}, - }) - assert.Nil(t, err) - assert.Equal(t, int32(100), maxValPassId) - - // Test failure case with MaxVal rule - var maxValFailureId int32 - err = v.Validate([]*v.Value{ - {Result: &maxValFailureId, Name: "id", Input: "101", Rules: []v.Rule{MaxVal(100)}}, - }) - assert.NotNil(t, err) - assert.Equal(t, int32(0), maxValFailureId) - - // Test string case - var stringId int32 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "hello world"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int32(0), stringId) - - // Test float case - var floatId int32 - err = v.Validate([]*v.Value{ - {Result: &floatId, Name: "id", Input: "20.1"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int32(0), floatId) - - // Test overflow case - var overflowId int32 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "2147483648"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int32(0), overflowId) -} - -// TestInt64 tests handing of an int64 as the result -func TestInt64(t *testing.T) { - // Test success case - var successId int64 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, int64(20), successId) - - // Test empty case - var emptyId int64 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, int64(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId int64 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, int64(0), emptyIsSetId) - - // Test overflow case - var overflowId int64 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "9223372036854775808"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int64(0), overflowId) - - // Test string case - var stringId int64 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, int64(0), stringId) -} - -// TestUint tests handing of a uint as the result -func TestUint(t *testing.T) { - // Test success case - var successId uint - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, uint(20), successId) - - // Test empty case - var emptyId uint - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, uint(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId uint - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint(0), emptyIsSetId) - - // Test overflow case - var overflowId uint - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "18446744073709551616"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint(0), overflowId) - - // Test string case - var stringId uint - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint(0), stringId) -} - -// TestUint8 tests handing of an uint8 as the result -func TestUint8(t *testing.T) { - // Test success case - var successId uint8 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, uint8(20), successId) - - // Test empty case - var emptyId uint8 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, uint8(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId uint8 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint8(0), emptyIsSetId) - - // Test overflow case - var overflowId uint8 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "256"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint8(0), overflowId) - - // Test string case - var stringId uint8 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint8(0), stringId) -} - -// TestUint16 tests handing of an uint16 as the result -func TestUint16(t *testing.T) { - // Test success case - var successId uint16 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, uint16(20), successId) - - // Test empty case - var emptyId uint16 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, uint16(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId uint16 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint16(0), emptyIsSetId) - - // Test overflow case - var overflowId uint16 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "65536"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint16(0), overflowId) - - // Test string case - var stringId uint16 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint16(0), stringId) -} - -// TestUint32 tests handing of an uint32 as the result -func TestUint32(t *testing.T) { - // Test success case - var successId uint32 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, uint32(20), successId) - - // Test empty case - var emptyId uint32 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, uint32(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId uint32 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint32(0), emptyIsSetId) - - // Test overflow case - var overflowId uint32 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "4294967296"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint32(0), overflowId) - - // Test string case - var stringId uint32 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint32(0), stringId) -} - -// TestUint64 tests handing of an uint64 as the result -func TestUint64(t *testing.T) { - // Test success case - var successId uint64 - err := v.Validate([]*v.Value{ - {Result: &successId, Name: "id", Input: "20"}, - }) - assert.Nil(t, err) - assert.Equal(t, uint64(20), successId) - - // Test empty case - var emptyId uint64 - err = v.Validate([]*v.Value{ - {Result: &emptyId, Name: "id", Input: ""}, - }) - assert.Nil(t, err) - assert.Equal(t, uint64(0), emptyId) - - // Test empty case with IsSet rule - var emptyIsSetId uint64 - err = v.Validate([]*v.Value{ - {Result: &emptyIsSetId, Name: "id", Input: "", Rules: []v.Rule{IsSet}}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint64(0), emptyIsSetId) - - // Test overflow case - var overflowId uint64 - err = v.Validate([]*v.Value{ - {Result: &overflowId, Name: "id", Input: "18446744073709551616"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint64(0), overflowId) - - // Test string case - var stringId uint64 - err = v.Validate([]*v.Value{ - {Result: &stringId, Name: "id", Input: "Hello World"}, - }) - assert.NotNil(t, err) - assert.Equal(t, uint64(0), stringId) -} - // TestCustomTypeHandler tests that we can create a new type handler // and use it as expected func TestCustomTypeHandler(t *testing.T) {