mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-14 20:22:20 +08:00
Support for min, max, regex, digit, digit_between, email, required, in.
This commit is contained in:
parent
fc5caf0706
commit
de318249e2
@ -3,11 +3,9 @@ package binding
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -150,56 +148,3 @@ func ensureNotPointer(obj interface{}) {
|
||||
panic("Pointers are not accepted as binding models")
|
||||
}
|
||||
}
|
||||
|
||||
func Validate(obj interface{}) error {
|
||||
typ := reflect.TypeOf(obj)
|
||||
val := reflect.ValueOf(obj)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
switch typ.Kind() {
|
||||
case reflect.Struct:
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
|
||||
// Allow ignored fields in the struct
|
||||
if field.Tag.Get("form") == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldValue := val.Field(i).Interface()
|
||||
zero := reflect.Zero(field.Type).Interface()
|
||||
|
||||
if strings.Index(field.Tag.Get("binding"), "required") > -1 {
|
||||
fieldType := field.Type.Kind()
|
||||
if fieldType == reflect.Struct {
|
||||
err := Validate(fieldValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if reflect.DeepEqual(zero, fieldValue) {
|
||||
return errors.New("Required " + field.Name)
|
||||
} else if fieldType == reflect.Slice && field.Type.Elem().Kind() == reflect.Struct {
|
||||
err := Validate(fieldValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
fieldValue := val.Index(i).Interface()
|
||||
err := Validate(fieldValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
280
binding/validate.go
Normal file
280
binding/validate.go
Normal file
@ -0,0 +1,280 @@
|
||||
package binding
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Validate(obj interface{}) error {
|
||||
|
||||
typ := reflect.TypeOf(obj)
|
||||
value := reflect.ValueOf(obj)
|
||||
|
||||
// Check to ensure we are getting a valid
|
||||
// pointer for manipulation.
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
value = value.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
|
||||
field := typ.Field(i)
|
||||
fieldValue := value.Field(i).Interface()
|
||||
zero := reflect.Zero(field.Type).Interface()
|
||||
|
||||
// Validate nested and embedded structs (if pointer, only do so if not nil)
|
||||
if field.Type.Kind() == reflect.Struct ||
|
||||
(field.Type.Kind() == reflect.Ptr && !reflect.DeepEqual(zero, fieldValue)) {
|
||||
if err := Validate(fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if field.Tag.Get("validate") != "" || field.Tag.Get("binding") != "" {
|
||||
// Break validate field into array
|
||||
array := strings.Split(field.Tag.Get("validate"), "|")
|
||||
|
||||
// Legacy Support for binding.
|
||||
if array[0] == "" {
|
||||
array = strings.Split(field.Tag.Get("binding"), "|")
|
||||
}
|
||||
|
||||
// Do the hard work of checking all assertions
|
||||
for setting := range array {
|
||||
|
||||
match := array[setting]
|
||||
|
||||
switch {
|
||||
case "required" == match:
|
||||
if err := required(field, fieldValue, zero); err != nil {
|
||||
return err
|
||||
}
|
||||
case "email" == match:
|
||||
fmt.Println("email...")
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := email(fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case strings.Contains(match, "digit:"):
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := digit(match, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case strings.Contains(match, "digits_between:"):
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := digits_between(match, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case strings.Contains(match, "min:"):
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := min(match, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case strings.Contains(match, "max:"):
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := max(match, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case strings.Contains(match, "in:"):
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := in(match, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case strings.Contains(match, "regex:"):
|
||||
if !reflect.DeepEqual(zero, fieldValue) {
|
||||
if err := regex(match, fieldValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Temp logging to check for errors
|
||||
errors.New(array[setting] + " is not a valid validation type.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check that the following function features
|
||||
// the required field. May need to check for
|
||||
// more special cases like since passing in null
|
||||
// is the same as 0 for int type checking.
|
||||
func required(field reflect.StructField, value, zero interface{}) error {
|
||||
|
||||
if reflect.DeepEqual(zero, value) {
|
||||
if _, ok := value.(int); !ok {
|
||||
return errors.New("The required field " + field.Name + " was not submitted.")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check that the passed in field is a valid email
|
||||
func email(value interface{}) error {
|
||||
// Email Regex Checker
|
||||
var emailRegex string = `^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`
|
||||
|
||||
if data, ok := value.(string); ok {
|
||||
if match, _ := regexp.Match(emailRegex, []byte(data)); match {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("A valid email address was not entered.")
|
||||
}
|
||||
} else {
|
||||
return errors.New("Email was not able to convert the passed in data to a []byte.")
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the passed in field is a valid email
|
||||
// Need to improve error logging for this method
|
||||
// Currently only supports strings, ints
|
||||
func in(field string, value interface{}) error {
|
||||
|
||||
if data, ok := value.(string); ok {
|
||||
|
||||
valid := strings.Split(field[3:], ",")
|
||||
|
||||
for option := range valid {
|
||||
if valid[option] == data {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("In did not match any of the expected values.")
|
||||
|
||||
} else if data, ok := value.(int); ok {
|
||||
// This will run with passed in data is an int
|
||||
valid := strings.Split(field[3:], ",")
|
||||
|
||||
for option := range valid {
|
||||
// Check for convertion to valid int
|
||||
if valint, err := strconv.ParseInt(valid[option], 0, 64); err == nil {
|
||||
if valint == int64(data) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("In did not match any of the expected values.")
|
||||
|
||||
} else {
|
||||
return errors.New("in, was not able to convert the data passed in to a string.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check that the passed in field is exactly X digits
|
||||
func digit(field string, value interface{}) error {
|
||||
|
||||
if data, ok := value.(int); ok {
|
||||
// Unpack number of digits it should be.
|
||||
digit := field[6:]
|
||||
|
||||
if digits, check := strconv.ParseInt(digit, 0, 64); check == nil {
|
||||
|
||||
if int64(len(strconv.FormatInt(int64(data), 10))) == digits {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("The data you passed in was not the right number of digits.")
|
||||
}
|
||||
|
||||
} else {
|
||||
return errors.New("Digit must check for a number.")
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("The number passed into digit was not an int.")
|
||||
}
|
||||
|
||||
func digits_between(field string, value interface{}) error {
|
||||
|
||||
if data, ok := value.(int); ok {
|
||||
|
||||
digit := strings.Split(field[15:], ",")
|
||||
|
||||
if digitSmall, ok := strconv.ParseInt(digit[0], 0, 64); ok == nil {
|
||||
|
||||
if digitLarge, okk := strconv.ParseInt(digit[1], 0, 64); okk == nil {
|
||||
|
||||
num := int64(len(strconv.FormatInt(int64(data), 10)))
|
||||
|
||||
if num >= digitSmall && num <= digitLarge {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("The data you passed in was not the right number of digits.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("The value passed into digits_between could not be converted to an int.")
|
||||
}
|
||||
|
||||
func min(field string, value interface{}) error {
|
||||
|
||||
if data, ok := value.(int); ok {
|
||||
|
||||
min := field[4:]
|
||||
|
||||
if minNum, ok := strconv.ParseInt(min, 0, 64); ok == nil {
|
||||
|
||||
if int64(data) >= minNum {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("The data you passed in was smaller then the allowed minimum.")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("The value passed into min could not be converted to an int.")
|
||||
}
|
||||
|
||||
func max(field string, value interface{}) error {
|
||||
|
||||
if data, ok := value.(int); ok {
|
||||
|
||||
max := field[4:]
|
||||
|
||||
if maxNum, ok := strconv.ParseInt(max, 0, 64); ok == nil {
|
||||
if int64(data) <= maxNum {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("The data you passed in was larger than the maximum.")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("The value passed into max could not be converted to an int.")
|
||||
}
|
||||
|
||||
func regex(field string, value interface{}) error {
|
||||
// Email Regex Checker
|
||||
|
||||
reg := field[6:]
|
||||
|
||||
if data, ok := value.(string); ok {
|
||||
if match, err := regexp.Match(reg, []byte(data)); err == nil && match {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("Your regex did not match or was not valid.")
|
||||
}
|
||||
} else {
|
||||
return errors.New("Regex was not able to convert the passed in data to a string.")
|
||||
}
|
||||
}
|
440
binding/validate_test.go
Normal file
440
binding/validate_test.go
Normal file
@ -0,0 +1,440 @@
|
||||
package binding
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Make string into io.ReadCloser
|
||||
// this is just for convinience
|
||||
func jsonFactory(s string) io.ReadCloser {
|
||||
return ioutil.NopCloser(strings.NewReader(s))
|
||||
}
|
||||
|
||||
// Ensure all required fields are matching
|
||||
func TestRequired(t *testing.T) {
|
||||
|
||||
// // Test if STRING required is valid
|
||||
var testString struct {
|
||||
Test string `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"something": "hello"}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testString); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testString2 struct {
|
||||
Test string `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testString2); err == nil {
|
||||
t.Error("Required string, empty JSON object should return error but did not.")
|
||||
}
|
||||
|
||||
// Test if INT require is valid
|
||||
var testInt struct {
|
||||
Test int `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"something": 2}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testInt); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Test if BOOL required is valid
|
||||
var testBool struct {
|
||||
Test bool `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"something": true}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testBool); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testBool2 struct {
|
||||
Test string `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testBool2); err == nil {
|
||||
t.Error("Required bool, empty JSON object should return error but did not.")
|
||||
}
|
||||
|
||||
// Test if ARRAY required is valid
|
||||
var testArray struct {
|
||||
Test []string `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"something": ["test", "data"]}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testArray); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Test is OBJECT required is valid
|
||||
type testObjectTP struct {
|
||||
Name string `json:"name" validate:"required" `
|
||||
}
|
||||
|
||||
var testObject struct {
|
||||
Test testObjectTP `json:"something" validate:"required" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"something": {"name": "test"}}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testObject); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
type testObjectTP2 struct {
|
||||
Name string `json:"name" validate:"required" `
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmail(t *testing.T) {
|
||||
|
||||
var testValEmail struct {
|
||||
Test string `json:"email" validate:"email" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"email": "michaeljs@gmail.com"}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValEmail); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValEmail2 struct {
|
||||
Test string `json:"email" validate:"email" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"email": "michaeljs@gail.edu"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValEmail2); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValEmail3 struct {
|
||||
Test string `json:"email" validate:"email" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"email": "michaeljs.edu"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValEmail3); err == nil {
|
||||
t.Error("Email test failed, michaeljs.edu passed as a valid email.")
|
||||
}
|
||||
|
||||
// This should not return an error since email is not required.
|
||||
var testValEmail4 struct {
|
||||
Test string `json:"email" validate:"email" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"jeff": "really"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValEmail4); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensure In is matching properly
|
||||
// Supporting string and int currently
|
||||
func TestIn(t *testing.T) {
|
||||
|
||||
var testValIn struct {
|
||||
Test string `json:"special" validate:"in:admin,user,other" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"special": "admin"}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValIn); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValIn2 struct {
|
||||
Test int `json:"special" validate:"in:1,3,2" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"special": 3}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValIn2); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValIn3 struct {
|
||||
Test int `json:"special" validate:"in:1,3,2" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"special": 6}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValIn3); err == nil {
|
||||
t.Error("6 is not in validate in call, err should not have been nil.")
|
||||
}
|
||||
|
||||
var testValIn4 struct {
|
||||
Test2 string `json:"what" validate:in:this,that`
|
||||
Test int `json:"special" validate:"in:1,3,2" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"special": 3,"what": "this"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValIn4); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValIn5 struct {
|
||||
Test2 string `json:"what" validate:in:this,that`
|
||||
Test int `json:"special" validate:"in:1,3,2" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"special": 3}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValIn5); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValIn6 struct {
|
||||
Test2 string `json:"what" validate:"in:this,that"`
|
||||
Test3 string `json:"what1" validate:"in:this,then"`
|
||||
Test4 string `json:"what2" validate:"in:this,that"`
|
||||
Test5 string `json:"what3" validate:"in:this,that"`
|
||||
Test int `json:"special" validate:"in:1,3,2"`
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"sa": 34, "what":"this", "what1":"then", "what2":"this"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValIn6); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the entered JSON is a data matching the one in a string.
|
||||
func TestDigit(t *testing.T) {
|
||||
|
||||
var testValDigit struct {
|
||||
Test int `json:"digit" validate:"digit:5" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"digit": 12345}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValDigit2 struct {
|
||||
Test int `json:"digit" validate:"digit:5" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 123456}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit2); err == nil {
|
||||
t.Error("Error should have been thrown, digits should be 5 but was 6.")
|
||||
}
|
||||
|
||||
var testValDigit3 struct {
|
||||
Test int `json:"digit" validate:"digit:12" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 111111111111}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit3); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check if the entered JSON is a data matching the one in a string.
|
||||
func TestDigitBetween(t *testing.T) {
|
||||
|
||||
var testValDigit struct {
|
||||
Test int `json:"digit" validate:"digits_between:5,7" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"digit": 123456}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValDigit2 struct {
|
||||
Test int `json:"digit" validate:"digits_between:0,10" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 1234564}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit2); err != nil {
|
||||
t.Error("Error should have been thrown, digit was not between 0 and 10.")
|
||||
}
|
||||
|
||||
var testValDigit3 struct {
|
||||
Test int `json:"digit" validate:"digits_between:0,1" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 1234564}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit3); err == nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check if the entered JSON is a data matching the one in a string.
|
||||
func TestMin(t *testing.T) {
|
||||
|
||||
var testValMin struct {
|
||||
Test int `json:"digit" validate:"min:23" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"digit": 24}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValMin); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValMin2 struct {
|
||||
Test int `json:"digit" validate:"min:20" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 19}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValMin2); err == nil {
|
||||
t.Error("Min was 20 digit of 19 should not have validated properly.")
|
||||
}
|
||||
|
||||
var testValMin3 struct {
|
||||
Test int `json:"digit" validate:"min:20" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"jeff":"greg"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValMin3); err != nil {
|
||||
t.Error("Nothing was entered but min was not required. No error should be thrown.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMax(t *testing.T) {
|
||||
|
||||
var testValMin struct {
|
||||
Test int `json:"digit" validate:"max:23" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"digit": 23}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValMin); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValMin2 struct {
|
||||
Test int `json:"digit" validate:"max:20" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 21}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValMin2); err == nil {
|
||||
t.Error("Max was 20 digit of 21 should not have validated properly.")
|
||||
}
|
||||
|
||||
var testValMin3 struct {
|
||||
Test int `json:"digit" validate:"max:20" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"jeff":"greg"}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValMin3); err != nil {
|
||||
t.Error("Nothing was entered but max was not required. No error should be thrown.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegex(t *testing.T) {
|
||||
|
||||
var testValDigit struct {
|
||||
Test int `json:"digit" validate:"regex:\d+" `
|
||||
}
|
||||
|
||||
testJSON := jsonFactory(`{"digit": 23}`)
|
||||
|
||||
req, _ := http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var testValDigit2 struct {
|
||||
Test int `json:"digit" validate:"regex:\d+" `
|
||||
}
|
||||
|
||||
testJSON = jsonFactory(`{"digit": 2dsa3}`)
|
||||
|
||||
req, _ = http.NewRequest("POST", "/", testJSON)
|
||||
|
||||
if err := JSON.Bind(req, &testValDigit2); err == nil {
|
||||
t.Error("\\d+ regex should not match the string 2dsa3.")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user