...

Source file src/github.com/gin-gonic/gin/binding/validate_test.go

Documentation: github.com/gin-gonic/gin/binding

     1  // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
     2  // Use of this source code is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package binding
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/go-playground/validator/v10"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  type testInterface interface {
    17  	String() string
    18  }
    19  
    20  type substructNoValidation struct {
    21  	IString string
    22  	IInt    int
    23  }
    24  
    25  type mapNoValidationSub map[string]substructNoValidation
    26  
    27  type structNoValidationValues struct {
    28  	substructNoValidation
    29  
    30  	Boolean bool
    31  
    32  	Uinteger   uint
    33  	Integer    int
    34  	Integer8   int8
    35  	Integer16  int16
    36  	Integer32  int32
    37  	Integer64  int64
    38  	Uinteger8  uint8
    39  	Uinteger16 uint16
    40  	Uinteger32 uint32
    41  	Uinteger64 uint64
    42  
    43  	Float32 float32
    44  	Float64 float64
    45  
    46  	String string
    47  
    48  	Date time.Time
    49  
    50  	Struct        substructNoValidation
    51  	InlinedStruct struct {
    52  		String  []string
    53  		Integer int
    54  	}
    55  
    56  	IntSlice           []int
    57  	IntPointerSlice    []*int
    58  	StructPointerSlice []*substructNoValidation
    59  	StructSlice        []substructNoValidation
    60  	InterfaceSlice     []testInterface
    61  
    62  	UniversalInterface any
    63  	CustomInterface    testInterface
    64  
    65  	FloatMap  map[string]float32
    66  	StructMap mapNoValidationSub
    67  }
    68  
    69  func createNoValidationValues() structNoValidationValues {
    70  	integer := 1
    71  	s := structNoValidationValues{
    72  		Boolean:            true,
    73  		Uinteger:           1 << 29,
    74  		Integer:            -10000,
    75  		Integer8:           120,
    76  		Integer16:          -20000,
    77  		Integer32:          1 << 29,
    78  		Integer64:          1 << 61,
    79  		Uinteger8:          250,
    80  		Uinteger16:         50000,
    81  		Uinteger32:         1 << 31,
    82  		Uinteger64:         1 << 62,
    83  		Float32:            123.456,
    84  		Float64:            123.456789,
    85  		String:             "text",
    86  		Date:               time.Time{},
    87  		CustomInterface:    &bytes.Buffer{},
    88  		Struct:             substructNoValidation{},
    89  		IntSlice:           []int{-3, -2, 1, 0, 1, 2, 3},
    90  		IntPointerSlice:    []*int{&integer},
    91  		StructSlice:        []substructNoValidation{},
    92  		UniversalInterface: 1.2,
    93  		FloatMap: map[string]float32{
    94  			"foo": 1.23,
    95  			"bar": 232.323,
    96  		},
    97  		StructMap: mapNoValidationSub{
    98  			"foo": substructNoValidation{},
    99  			"bar": substructNoValidation{},
   100  		},
   101  		// StructPointerSlice []noValidationSub
   102  		// InterfaceSlice     []testInterface
   103  	}
   104  	s.InlinedStruct.Integer = 1000
   105  	s.InlinedStruct.String = []string{"first", "second"}
   106  	s.IString = "substring"
   107  	s.IInt = 987654
   108  	return s
   109  }
   110  
   111  func TestValidateNoValidationValues(t *testing.T) {
   112  	origin := createNoValidationValues()
   113  	test := createNoValidationValues()
   114  	empty := structNoValidationValues{}
   115  
   116  	assert.Nil(t, validate(test))
   117  	assert.Nil(t, validate(&test))
   118  	assert.Nil(t, validate(empty))
   119  	assert.Nil(t, validate(&empty))
   120  
   121  	assert.Equal(t, origin, test)
   122  }
   123  
   124  type structNoValidationPointer struct {
   125  	substructNoValidation
   126  
   127  	Boolean bool
   128  
   129  	Uinteger   *uint
   130  	Integer    *int
   131  	Integer8   *int8
   132  	Integer16  *int16
   133  	Integer32  *int32
   134  	Integer64  *int64
   135  	Uinteger8  *uint8
   136  	Uinteger16 *uint16
   137  	Uinteger32 *uint32
   138  	Uinteger64 *uint64
   139  
   140  	Float32 *float32
   141  	Float64 *float64
   142  
   143  	String *string
   144  
   145  	Date *time.Time
   146  
   147  	Struct *substructNoValidation
   148  
   149  	IntSlice           *[]int
   150  	IntPointerSlice    *[]*int
   151  	StructPointerSlice *[]*substructNoValidation
   152  	StructSlice        *[]substructNoValidation
   153  	InterfaceSlice     *[]testInterface
   154  
   155  	FloatMap  *map[string]float32
   156  	StructMap *mapNoValidationSub
   157  }
   158  
   159  func TestValidateNoValidationPointers(t *testing.T) {
   160  	//origin := createNoValidation_values()
   161  	//test := createNoValidation_values()
   162  	empty := structNoValidationPointer{}
   163  
   164  	//assert.Nil(t, validate(test))
   165  	//assert.Nil(t, validate(&test))
   166  	assert.Nil(t, validate(empty))
   167  	assert.Nil(t, validate(&empty))
   168  
   169  	//assert.Equal(t, origin, test)
   170  }
   171  
   172  type Object map[string]any
   173  
   174  func TestValidatePrimitives(t *testing.T) {
   175  	obj := Object{"foo": "bar", "bar": 1}
   176  	assert.NoError(t, validate(obj))
   177  	assert.NoError(t, validate(&obj))
   178  	assert.Equal(t, Object{"foo": "bar", "bar": 1}, obj)
   179  
   180  	obj2 := []Object{{"foo": "bar", "bar": 1}, {"foo": "bar", "bar": 1}}
   181  	assert.NoError(t, validate(obj2))
   182  	assert.NoError(t, validate(&obj2))
   183  
   184  	nu := 10
   185  	assert.NoError(t, validate(nu))
   186  	assert.NoError(t, validate(&nu))
   187  	assert.Equal(t, 10, nu)
   188  
   189  	str := "value"
   190  	assert.NoError(t, validate(str))
   191  	assert.NoError(t, validate(&str))
   192  	assert.Equal(t, "value", str)
   193  }
   194  
   195  // structCustomValidation is a helper struct we use to check that
   196  // custom validation can be registered on it.
   197  // The `notone` binding directive is for custom validation and registered later.
   198  type structCustomValidation struct {
   199  	Integer int `binding:"notone"`
   200  }
   201  
   202  func notOne(f1 validator.FieldLevel) bool {
   203  	if val, ok := f1.Field().Interface().(int); ok {
   204  		return val != 1
   205  	}
   206  	return false
   207  }
   208  
   209  func TestValidatorEngine(t *testing.T) {
   210  	// This validates that the function `notOne` matches
   211  	// the expected function signature by `defaultValidator`
   212  	// and by extension the validator library.
   213  	engine, ok := Validator.Engine().(*validator.Validate)
   214  	assert.True(t, ok)
   215  
   216  	err := engine.RegisterValidation("notone", notOne)
   217  	// Check that we can register custom validation without error
   218  	assert.Nil(t, err)
   219  
   220  	// Create an instance which will fail validation
   221  	withOne := structCustomValidation{Integer: 1}
   222  	errs := validate(withOne)
   223  
   224  	// Check that we got back non-nil errs
   225  	assert.NotNil(t, errs)
   226  	// Check that the error matches expectation
   227  	assert.Error(t, errs, "", "", "notone")
   228  }
   229  

View as plain text