...

Source file src/github.com/go-openapi/validate/validator_test.go

Documentation: github.com/go-openapi/validate

     1  // Copyright 2015 go-swagger maintainers
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package validate
    16  
    17  import (
    18  	"math"
    19  	"reflect"
    20  	"testing"
    21  
    22  	"github.com/go-openapi/spec"
    23  	"github.com/go-openapi/strfmt"
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestHeaderValidator(t *testing.T) {
    29  	t.Run("with no recycling", func(t *testing.T) {
    30  		v := NewHeaderValidator("header", &spec.Header{}, strfmt.Default, SwaggerSchema(true))
    31  
    32  		res := v.Validate(nil)
    33  		require.Nil(t, res)
    34  	})
    35  
    36  	t.Run("with recycling", func(t *testing.T) {
    37  		v := NewHeaderValidator("header", &spec.Header{}, strfmt.Default,
    38  			SwaggerSchema(true), WithRecycleValidators(true), withRecycleResults(true),
    39  		)
    40  
    41  		t.Run("should validate nil data", func(t *testing.T) {
    42  			res := v.Validate(nil)
    43  			require.Nil(t, res)
    44  		})
    45  
    46  		t.Run("should validate only once", func(t *testing.T) {
    47  			// we should not do that: the pool chain list is populated with a duplicate: needs a reset
    48  			t.Cleanup(resetPools)
    49  			require.Panics(t, func() {
    50  				_ = v.Validate("header")
    51  			})
    52  		})
    53  		t.Run("should validate non nil data", func(t *testing.T) {
    54  			nv := NewHeaderValidator("header", &spec.Header{SimpleSchema: spec.SimpleSchema{Type: "string"}}, strfmt.Default,
    55  				SwaggerSchema(true), WithRecycleValidators(true), withRecycleResults(true),
    56  			)
    57  
    58  			res := nv.Validate("X-GO")
    59  			require.NotNil(t, res)
    60  			require.Empty(t, res.Errors)
    61  			require.True(t, res.wantsRedeemOnMerge)
    62  			pools.poolOfResults.RedeemResult(res)
    63  		})
    64  	})
    65  }
    66  
    67  func TestParamValidator(t *testing.T) {
    68  	v := NewParamValidator(&spec.Parameter{}, strfmt.Default, SwaggerSchema(true))
    69  
    70  	res := v.Validate(nil)
    71  	require.Nil(t, res)
    72  }
    73  
    74  func TestNumberValidator_EdgeCases(t *testing.T) {
    75  	// Apply
    76  	var min = float64(math.MinInt32 - 1)
    77  	var max = float64(math.MaxInt32 + 1)
    78  
    79  	v := newNumberValidator(
    80  		"path",
    81  		"in",
    82  		nil,
    83  		nil,
    84  		&max, // *float64
    85  		false,
    86  		&min, // *float64
    87  		false,
    88  		// Allows for more accurate behavior regarding integers
    89  		"integer",
    90  		"int32",
    91  		nil,
    92  	)
    93  
    94  	// numberValidator applies to: Parameter,Schema,Items,Header
    95  
    96  	sources := []interface{}{
    97  		new(spec.Parameter),
    98  		new(spec.Schema),
    99  		new(spec.Items),
   100  		new(spec.Header),
   101  	}
   102  
   103  	testNumberApply(t, v, sources)
   104  
   105  	assert.False(t, v.Applies(float64(32), reflect.Float64))
   106  
   107  	// Now for different scenarios on Minimum, Maximum
   108  	// - The Maximum value does not respect the Type|Format specification
   109  	// - Value is checked as float64 with Maximum as float64 and fails
   110  	res := v.Validate(int64(math.MaxInt32 + 2))
   111  	assert.True(t, res.HasErrors())
   112  	// - The Minimum value does not respect the Type|Format specification
   113  	// - Value is checked as float64 with Maximum as float64 and fails
   114  	res = v.Validate(int64(math.MinInt32 - 2))
   115  	assert.True(t, res.HasErrors())
   116  }
   117  
   118  func testNumberApply(t *testing.T, v *numberValidator, sources []interface{}) {
   119  	for _, source := range sources {
   120  		// numberValidator does not applies to:
   121  		assert.False(t, v.Applies(source, reflect.String))
   122  		assert.False(t, v.Applies(source, reflect.Struct))
   123  		// numberValidator applies to:
   124  		assert.True(t, v.Applies(source, reflect.Int))
   125  		assert.True(t, v.Applies(source, reflect.Int8))
   126  		assert.True(t, v.Applies(source, reflect.Uint16))
   127  		assert.True(t, v.Applies(source, reflect.Uint32))
   128  		assert.True(t, v.Applies(source, reflect.Uint64))
   129  		assert.True(t, v.Applies(source, reflect.Uint))
   130  		assert.True(t, v.Applies(source, reflect.Uint8))
   131  		assert.True(t, v.Applies(source, reflect.Uint16))
   132  		assert.True(t, v.Applies(source, reflect.Uint32))
   133  		assert.True(t, v.Applies(source, reflect.Uint64))
   134  		assert.True(t, v.Applies(source, reflect.Float32))
   135  		assert.True(t, v.Applies(source, reflect.Float64))
   136  	}
   137  }
   138  
   139  func TestStringValidator_EdgeCases(t *testing.T) {
   140  	// Apply
   141  
   142  	v := newStringValidator(
   143  		"", "", nil, false, false, nil, nil, "", nil,
   144  	)
   145  
   146  	// stringValidator applies to: Parameter,Schema,Items,Header
   147  
   148  	sources := []interface{}{
   149  		new(spec.Parameter),
   150  		new(spec.Schema),
   151  		new(spec.Items),
   152  		new(spec.Header),
   153  	}
   154  
   155  	testStringApply(t, v, sources)
   156  
   157  	assert.False(t, v.Applies("A string", reflect.String))
   158  }
   159  
   160  func testStringApply(t *testing.T, v *stringValidator, sources []interface{}) {
   161  	for _, source := range sources {
   162  		// numberValidator does not applies to:
   163  		assert.False(t, v.Applies(source, reflect.Struct))
   164  		assert.False(t, v.Applies(source, reflect.Int))
   165  		// numberValidator applies to:
   166  		assert.True(t, v.Applies(source, reflect.String))
   167  	}
   168  }
   169  
   170  func TestBasicCommonValidator_EdgeCases(t *testing.T) {
   171  	// Apply
   172  
   173  	v := newBasicCommonValidator(
   174  		"", "",
   175  		nil, []interface{}{"a", nil, 3}, nil,
   176  	)
   177  
   178  	// basicCommonValidator applies to: Parameter,Schema,Header
   179  
   180  	sources := []interface{}{
   181  		new(spec.Parameter),
   182  		new(spec.Schema),
   183  		new(spec.Header),
   184  	}
   185  
   186  	testCommonApply(t, v, sources)
   187  
   188  	assert.False(t, v.Applies("A string", reflect.String))
   189  
   190  	t.Run("should validate Enum", func(t *testing.T) {
   191  		res := v.Validate("a")
   192  		require.Nil(t, res)
   193  
   194  		res = v.Validate(3)
   195  		require.Nil(t, res)
   196  
   197  		res = v.Validate("b")
   198  		require.NotNil(t, res)
   199  		assert.True(t, res.HasErrors())
   200  	})
   201  
   202  	t.Run("shoud validate empty Enum", func(t *testing.T) {
   203  		ev := newBasicCommonValidator(
   204  			"", "",
   205  			nil, nil, nil,
   206  		)
   207  		res := ev.Validate("a")
   208  		require.Nil(t, res)
   209  
   210  		res = ev.Validate(3)
   211  		require.Nil(t, res)
   212  
   213  		res = ev.Validate("b")
   214  		require.Nil(t, res)
   215  	})
   216  }
   217  
   218  func testCommonApply(t *testing.T, v *basicCommonValidator, sources []interface{}) {
   219  	for _, source := range sources {
   220  		assert.True(t, v.Applies(source, reflect.String))
   221  	}
   222  }
   223  
   224  func TestBasicSliceValidator_EdgeCases(t *testing.T) {
   225  	t.Run("should Apply", func(t *testing.T) {
   226  		v := newBasicSliceValidator(
   227  			"", "",
   228  			nil, nil, nil, false, nil, nil, strfmt.Default, nil,
   229  		)
   230  
   231  		// basicCommonValidator applies to: Parameter,Schema,Header
   232  
   233  		sources := []interface{}{
   234  			new(spec.Parameter),
   235  			new(spec.Items),
   236  			new(spec.Header),
   237  		}
   238  
   239  		testSliceApply(t, v, sources)
   240  
   241  		assert.False(t, v.Applies(new(spec.Schema), reflect.Slice))
   242  		assert.False(t, v.Applies(new(spec.Parameter), reflect.String))
   243  	})
   244  
   245  	t.Run("with recycling", func(t *testing.T) {
   246  		v := newBasicSliceValidator(
   247  			"", "",
   248  			nil, nil, nil, false, nil, nil, strfmt.Default,
   249  			&SchemaValidatorOptions{recycleValidators: true},
   250  		)
   251  
   252  		res := v.Validate([]int{})
   253  		require.Nil(t, res)
   254  	})
   255  }
   256  
   257  func testSliceApply(t *testing.T, v *basicSliceValidator, sources []interface{}) {
   258  	for _, source := range sources {
   259  		assert.True(t, v.Applies(source, reflect.Slice))
   260  	}
   261  }
   262  
   263  /* unused
   264  type anything struct {
   265  	anyProperty int
   266  }
   267  
   268  // hasDuplicates() is currently not exercised by common spec testcases
   269  // (this method is not used by the validator atm)
   270  // Here is a unit exerciser
   271  // NOTE: this method is probably obsolete and superseeded by values.go:UniqueItems()
   272  // which is superior in every respect to this one.
   273  func TestBasicSliceValidator_HasDuplicates(t *testing.T) {
   274  	s := basicSliceValidator{}
   275  	// hasDuplicates() makes no hypothesis about the underlying object,
   276  	// save being an array, slice or string (same constraint as reflect.Value.Index())
   277  	// it also comes without safeguard or anything.
   278  	vi := []int{1, 2, 3}
   279  	vs := []string{"a", "b", "c"}
   280  	vt := []anything{
   281  		{anyProperty: 1},
   282  		{anyProperty: 2},
   283  		{anyProperty: 3},
   284  	}
   285  	assert.False(t, s.hasDuplicates(reflect.ValueOf(vi), len(vi)))
   286  	assert.False(t, s.hasDuplicates(reflect.ValueOf(vs), len(vs)))
   287  	assert.False(t, s.hasDuplicates(reflect.ValueOf(vt), len(vt)))
   288  
   289  	di := []int{1, 1, 3}
   290  	ds := []string{"a", "b", "a"}
   291  	dt := []anything{
   292  		{anyProperty: 1},
   293  		{anyProperty: 2},
   294  		{anyProperty: 2},
   295  	}
   296  	assert.True(t, s.hasDuplicates(reflect.ValueOf(di), len(di)))
   297  	assert.True(t, s.hasDuplicates(reflect.ValueOf(ds), len(ds)))
   298  	assert.True(t, s.hasDuplicates(reflect.ValueOf(dt), len(dt)))
   299  }
   300  */
   301  

View as plain text