File: //proc/self/root/opt/go/pkg/mod/github.com/go-openapi/
[email protected]/validator_test.go
// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validate
import (
"math"
"reflect"
"testing"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestHeaderValidator(t *testing.T) {
t.Run("with no recycling", func(t *testing.T) {
v := NewHeaderValidator("header", &spec.Header{}, strfmt.Default, SwaggerSchema(true))
res := v.Validate(nil)
require.Nil(t, res)
})
t.Run("with recycling", func(t *testing.T) {
v := NewHeaderValidator("header", &spec.Header{}, strfmt.Default,
SwaggerSchema(true), WithRecycleValidators(true), withRecycleResults(true),
)
t.Run("should validate nil data", func(t *testing.T) {
res := v.Validate(nil)
require.Nil(t, res)
})
t.Run("should validate only once", func(t *testing.T) {
// we should not do that: the pool chain list is populated with a duplicate: needs a reset
t.Cleanup(resetPools)
require.Panics(t, func() {
_ = v.Validate("header")
})
})
t.Run("should validate non nil data", func(t *testing.T) {
nv := NewHeaderValidator("header", &spec.Header{SimpleSchema: spec.SimpleSchema{Type: "string"}}, strfmt.Default,
SwaggerSchema(true), WithRecycleValidators(true), withRecycleResults(true),
)
res := nv.Validate("X-GO")
require.NotNil(t, res)
require.Empty(t, res.Errors)
require.True(t, res.wantsRedeemOnMerge)
pools.poolOfResults.RedeemResult(res)
})
})
}
func TestParamValidator(t *testing.T) {
v := NewParamValidator(&spec.Parameter{}, strfmt.Default, SwaggerSchema(true))
res := v.Validate(nil)
require.Nil(t, res)
}
func TestNumberValidator_EdgeCases(t *testing.T) {
// Apply
var min = float64(math.MinInt32 - 1)
var max = float64(math.MaxInt32 + 1)
v := newNumberValidator(
"path",
"in",
nil,
nil,
&max, // *float64
false,
&min, // *float64
false,
// Allows for more accurate behavior regarding integers
"integer",
"int32",
nil,
)
// numberValidator applies to: Parameter,Schema,Items,Header
sources := []interface{}{
new(spec.Parameter),
new(spec.Schema),
new(spec.Items),
new(spec.Header),
}
testNumberApply(t, v, sources)
assert.False(t, v.Applies(float64(32), reflect.Float64))
// Now for different scenarios on Minimum, Maximum
// - The Maximum value does not respect the Type|Format specification
// - Value is checked as float64 with Maximum as float64 and fails
res := v.Validate(int64(math.MaxInt32 + 2))
assert.True(t, res.HasErrors())
// - The Minimum value does not respect the Type|Format specification
// - Value is checked as float64 with Maximum as float64 and fails
res = v.Validate(int64(math.MinInt32 - 2))
assert.True(t, res.HasErrors())
}
func testNumberApply(t *testing.T, v *numberValidator, sources []interface{}) {
for _, source := range sources {
// numberValidator does not applies to:
assert.False(t, v.Applies(source, reflect.String))
assert.False(t, v.Applies(source, reflect.Struct))
// numberValidator applies to:
assert.True(t, v.Applies(source, reflect.Int))
assert.True(t, v.Applies(source, reflect.Int8))
assert.True(t, v.Applies(source, reflect.Uint16))
assert.True(t, v.Applies(source, reflect.Uint32))
assert.True(t, v.Applies(source, reflect.Uint64))
assert.True(t, v.Applies(source, reflect.Uint))
assert.True(t, v.Applies(source, reflect.Uint8))
assert.True(t, v.Applies(source, reflect.Uint16))
assert.True(t, v.Applies(source, reflect.Uint32))
assert.True(t, v.Applies(source, reflect.Uint64))
assert.True(t, v.Applies(source, reflect.Float32))
assert.True(t, v.Applies(source, reflect.Float64))
}
}
func TestStringValidator_EdgeCases(t *testing.T) {
// Apply
v := newStringValidator(
"", "", nil, false, false, nil, nil, "", nil,
)
// stringValidator applies to: Parameter,Schema,Items,Header
sources := []interface{}{
new(spec.Parameter),
new(spec.Schema),
new(spec.Items),
new(spec.Header),
}
testStringApply(t, v, sources)
assert.False(t, v.Applies("A string", reflect.String))
}
func testStringApply(t *testing.T, v *stringValidator, sources []interface{}) {
for _, source := range sources {
// numberValidator does not applies to:
assert.False(t, v.Applies(source, reflect.Struct))
assert.False(t, v.Applies(source, reflect.Int))
// numberValidator applies to:
assert.True(t, v.Applies(source, reflect.String))
}
}
func TestBasicCommonValidator_EdgeCases(t *testing.T) {
// Apply
v := newBasicCommonValidator(
"", "",
nil, []interface{}{"a", nil, 3}, nil,
)
// basicCommonValidator applies to: Parameter,Schema,Header
sources := []interface{}{
new(spec.Parameter),
new(spec.Schema),
new(spec.Header),
}
testCommonApply(t, v, sources)
assert.False(t, v.Applies("A string", reflect.String))
t.Run("should validate Enum", func(t *testing.T) {
res := v.Validate("a")
require.Nil(t, res)
res = v.Validate(3)
require.Nil(t, res)
res = v.Validate("b")
require.NotNil(t, res)
assert.True(t, res.HasErrors())
})
t.Run("shoud validate empty Enum", func(t *testing.T) {
ev := newBasicCommonValidator(
"", "",
nil, nil, nil,
)
res := ev.Validate("a")
require.Nil(t, res)
res = ev.Validate(3)
require.Nil(t, res)
res = ev.Validate("b")
require.Nil(t, res)
})
}
func testCommonApply(t *testing.T, v *basicCommonValidator, sources []interface{}) {
for _, source := range sources {
assert.True(t, v.Applies(source, reflect.String))
}
}
func TestBasicSliceValidator_EdgeCases(t *testing.T) {
t.Run("should Apply", func(t *testing.T) {
v := newBasicSliceValidator(
"", "",
nil, nil, nil, false, nil, nil, strfmt.Default, nil,
)
// basicCommonValidator applies to: Parameter,Schema,Header
sources := []interface{}{
new(spec.Parameter),
new(spec.Items),
new(spec.Header),
}
testSliceApply(t, v, sources)
assert.False(t, v.Applies(new(spec.Schema), reflect.Slice))
assert.False(t, v.Applies(new(spec.Parameter), reflect.String))
})
t.Run("with recycling", func(t *testing.T) {
v := newBasicSliceValidator(
"", "",
nil, nil, nil, false, nil, nil, strfmt.Default,
&SchemaValidatorOptions{recycleValidators: true},
)
res := v.Validate([]int{})
require.Nil(t, res)
})
}
func testSliceApply(t *testing.T, v *basicSliceValidator, sources []interface{}) {
for _, source := range sources {
assert.True(t, v.Applies(source, reflect.Slice))
}
}
/* unused
type anything struct {
anyProperty int
}
// hasDuplicates() is currently not exercised by common spec testcases
// (this method is not used by the validator atm)
// Here is a unit exerciser
// NOTE: this method is probably obsolete and superseeded by values.go:UniqueItems()
// which is superior in every respect to this one.
func TestBasicSliceValidator_HasDuplicates(t *testing.T) {
s := basicSliceValidator{}
// hasDuplicates() makes no hypothesis about the underlying object,
// save being an array, slice or string (same constraint as reflect.Value.Index())
// it also comes without safeguard or anything.
vi := []int{1, 2, 3}
vs := []string{"a", "b", "c"}
vt := []anything{
{anyProperty: 1},
{anyProperty: 2},
{anyProperty: 3},
}
assert.False(t, s.hasDuplicates(reflect.ValueOf(vi), len(vi)))
assert.False(t, s.hasDuplicates(reflect.ValueOf(vs), len(vs)))
assert.False(t, s.hasDuplicates(reflect.ValueOf(vt), len(vt)))
di := []int{1, 1, 3}
ds := []string{"a", "b", "a"}
dt := []anything{
{anyProperty: 1},
{anyProperty: 2},
{anyProperty: 2},
}
assert.True(t, s.hasDuplicates(reflect.ValueOf(di), len(di)))
assert.True(t, s.hasDuplicates(reflect.ValueOf(ds), len(ds)))
assert.True(t, s.hasDuplicates(reflect.ValueOf(dt), len(dt)))
}
*/