...

Source file src/github.com/go-openapi/validate/values_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  	"context"
    19  	"math"
    20  	"testing"
    21  
    22  	"github.com/go-openapi/errors"
    23  	"github.com/go-openapi/strfmt"
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestValues_ValidateIntEnum(t *testing.T) {
    29  	enumValues := []interface{}{1, 2, 3}
    30  
    31  	require.Error(t, Enum("test", "body", int64(5), enumValues))
    32  	require.Nil(t, Enum("test", "body", int64(1), enumValues))
    33  }
    34  
    35  func TestValues_ValidateEnum(t *testing.T) {
    36  	enumValues := []string{"aa", "bb", "cc"}
    37  
    38  	require.Error(t, Enum("test", "body", "a", enumValues))
    39  	require.Nil(t, Enum("test", "body", "bb", enumValues))
    40  
    41  	type CustomString string
    42  
    43  	require.Error(t, Enum("test", "body", CustomString("a"), enumValues))
    44  	require.Nil(t, Enum("test", "body", CustomString("bb"), enumValues))
    45  }
    46  
    47  func TestValues_ValidateNilEnum(t *testing.T) {
    48  	enumValues := []string{"aa", "bb", "cc"}
    49  
    50  	require.Error(t, Enum("test", "body", nil, enumValues))
    51  }
    52  
    53  // Check edge cases in Enum
    54  func TestValues_Enum_EdgeCases(t *testing.T) {
    55  	enumValues := "aa, bb, cc"
    56  
    57  	// No validation occurs: enumValues is not a slice
    58  	require.Nil(t, Enum("test", "body", int64(1), enumValues))
    59  
    60  	// TODO(TEST): edge case: value is not a concrete type
    61  	// It's really a go internals challenge
    62  	// to figure a test case to demonstrate
    63  	// this case must be checked (!!)
    64  }
    65  
    66  func TestValues_ValidateEnumCaseInsensitive(t *testing.T) {
    67  	enumValues := []string{"aa", "bb", "cc"}
    68  
    69  	require.Error(t, EnumCase("test", "body", "a", enumValues, true))
    70  	require.Nil(t, EnumCase("test", "body", "bb", enumValues, true))
    71  	require.Error(t, EnumCase("test", "body", "BB", enumValues, true))
    72  	require.Error(t, EnumCase("test", "body", "a", enumValues, false))
    73  	require.Nil(t, EnumCase("test", "body", "bb", enumValues, false))
    74  	require.Nil(t, EnumCase("test", "body", "BB", enumValues, false))
    75  	require.Error(t, EnumCase("test", "body", int64(1), enumValues, false))
    76  }
    77  
    78  func TestValues_ValidateUniqueItems(t *testing.T) {
    79  	itemsNonUnique := []interface{}{
    80  		[]int32{1, 2, 3, 4, 4, 5},
    81  		[]string{"aa", "bb", "cc", "cc", "dd"},
    82  	}
    83  	for _, v := range itemsNonUnique {
    84  		require.Error(t, UniqueItems("test", "body", v))
    85  	}
    86  
    87  	itemsUnique := []interface{}{
    88  		[]int32{1, 2, 3},
    89  		"I'm a string",
    90  		map[string]int{
    91  			"aaa": 1111,
    92  			"b":   2,
    93  			"ccc": 333,
    94  		},
    95  		nil,
    96  	}
    97  	for _, v := range itemsUnique {
    98  		require.Nil(t, UniqueItems("test", "body", v))
    99  	}
   100  }
   101  
   102  func TestValues_ValidateMinLength(t *testing.T) {
   103  	const minLength = int64(5)
   104  	require.Error(t, MinLength("test", "body", "aa", minLength))
   105  	require.Nil(t, MinLength("test", "body", "aaaaa", minLength))
   106  }
   107  
   108  func TestValues_ValidateMaxLength(t *testing.T) {
   109  	const maxLength = int64(5)
   110  	require.Error(t, MaxLength("test", "body", "bbbbbb", maxLength))
   111  	require.Nil(t, MaxLength("test", "body", "aa", maxLength))
   112  }
   113  
   114  func TestValues_ReadOnly(t *testing.T) {
   115  	const (
   116  		path = "test"
   117  		in   = "body"
   118  	)
   119  
   120  	ReadOnlySuccess := []interface{}{
   121  		"",
   122  		0,
   123  		nil,
   124  	}
   125  
   126  	// fail only when operation type is request
   127  	ReadOnlyFail := []interface{}{
   128  		" ",
   129  		"bla-bla-bla",
   130  		2,
   131  		[]interface{}{21, []int{}, "testString"},
   132  	}
   133  
   134  	t.Run("No operation context", func(t *testing.T) {
   135  		// readonly should not have any effect
   136  		ctx := context.Background()
   137  		for _, v := range ReadOnlySuccess {
   138  			require.Nil(t, ReadOnly(ctx, path, in, v))
   139  		}
   140  		for _, v := range ReadOnlyFail {
   141  			require.Nil(t, ReadOnly(ctx, path, in, v))
   142  		}
   143  
   144  	})
   145  	t.Run("operationType request", func(t *testing.T) {
   146  		ctx := WithOperationRequest(context.Background())
   147  		for _, v := range ReadOnlySuccess {
   148  			require.Nil(t, ReadOnly(ctx, path, in, v))
   149  		}
   150  		for _, v := range ReadOnlyFail {
   151  			require.Error(t, ReadOnly(ctx, path, in, v))
   152  		}
   153  	})
   154  	t.Run("operationType response", func(t *testing.T) {
   155  		ctx := WithOperationResponse(context.Background())
   156  		for _, v := range ReadOnlySuccess {
   157  			require.Nil(t, ReadOnly(ctx, path, in, v))
   158  		}
   159  		for _, v := range ReadOnlyFail {
   160  			require.Nil(t, ReadOnly(ctx, path, in, v))
   161  		}
   162  	})
   163  }
   164  
   165  func TestValues_ValidateRequired(t *testing.T) {
   166  	const (
   167  		path = "test"
   168  		in   = "body"
   169  	)
   170  
   171  	RequiredFail := []interface{}{
   172  		"",
   173  		0,
   174  		nil,
   175  	}
   176  
   177  	for _, v := range RequiredFail {
   178  		require.Error(t, Required(path, in, v))
   179  	}
   180  
   181  	RequiredSuccess := []interface{}{
   182  		" ",
   183  		"bla-bla-bla",
   184  		2,
   185  		[]interface{}{21, []int{}, "testString"},
   186  	}
   187  
   188  	for _, v := range RequiredSuccess {
   189  		require.Nil(t, Required(path, in, v))
   190  	}
   191  
   192  }
   193  
   194  func TestValues_ValidateRequiredNumber(t *testing.T) {
   195  	require.Error(t, RequiredNumber("test", "body", 0))
   196  	require.Nil(t, RequiredNumber("test", "body", 1))
   197  }
   198  
   199  func TestValuMultipleOf(t *testing.T) {
   200  	// positive
   201  	require.Nil(t, MultipleOf("test", "body", 9, 3))
   202  	require.Nil(t, MultipleOf("test", "body", 9.3, 3.1))
   203  	require.Nil(t, MultipleOf("test", "body", 9.1, 0.1))
   204  	require.Nil(t, MultipleOf("test", "body", 3, 0.3))
   205  	require.Nil(t, MultipleOf("test", "body", 6, 0.3))
   206  	require.Nil(t, MultipleOf("test", "body", 1, 0.25))
   207  	require.Nil(t, MultipleOf("test", "body", 8, 0.2))
   208  
   209  	// zero
   210  	require.Error(t, MultipleOf("test", "body", 9, 0))
   211  	require.Error(t, MultipleOf("test", "body", 9.1, 0))
   212  
   213  	// negative
   214  	require.Error(t, MultipleOf("test", "body", 3, 0.4))
   215  	require.Error(t, MultipleOf("test", "body", 9.1, 0.2))
   216  	require.Error(t, MultipleOf("test", "body", 9.34, 0.1))
   217  
   218  	// error on negative factor
   219  	require.Error(t, MultipleOf("test", "body", 9.34, -0.1))
   220  }
   221  
   222  // Test edge case for Pattern (in regular spec, no invalid regexp should reach there)
   223  func TestValues_Pattern_Edgecases(t *testing.T) {
   224  	require.Nil(t, Pattern("path", "in", "pick-a-boo", `.*-[a-z]-.*`))
   225  
   226  	t.Run("with invalid regexp", func(t *testing.T) {
   227  		err := Pattern("path", "in", "pick-a-boo", `.*-[a(-z]-^).*`)
   228  		require.Error(t, err)
   229  		assert.Equal(t, int(err.Code()), int(errors.PatternFailCode))
   230  		assert.Contains(t, err.Error(), "pattern is invalid")
   231  	})
   232  
   233  	t.Run("with valid regexp, invalid pattern", func(t *testing.T) {
   234  		err := Pattern("path", "in", "pick-8-boo", `.*-[a-z]-.*`)
   235  		require.Error(t, err)
   236  		assert.Equal(t, int(err.Code()), int(errors.PatternFailCode))
   237  		assert.NotContains(t, err.Error(), "pattern is invalid")
   238  		assert.Contains(t, err.Error(), "should match")
   239  	})
   240  }
   241  
   242  // Test edge cases in FormatOf
   243  // not easily tested with full specs
   244  func TestValues_FormatOf_EdgeCases(t *testing.T) {
   245  	var err *errors.Validation
   246  
   247  	err = FormatOf("path", "in", "bugz", "", nil)
   248  	require.Error(t, err)
   249  	assert.Equal(t, int(err.Code()), int(errors.InvalidTypeCode))
   250  	assert.Contains(t, err.Error(), "bugz is an invalid type name")
   251  
   252  	err = FormatOf("path", "in", "bugz", "", strfmt.Default)
   253  	require.Error(t, err)
   254  	assert.Equal(t, int(err.Code()), int(errors.InvalidTypeCode))
   255  	assert.Contains(t, err.Error(), "bugz is an invalid type name")
   256  }
   257  
   258  // Test edge cases in MaximumNativeType
   259  // not easily exercised with full specs
   260  func TestValues_MaximumNative(t *testing.T) {
   261  	require.Nil(t, MaximumNativeType("path", "in", int(5), 10, false))
   262  	require.Nil(t, MaximumNativeType("path", "in", uint(5), 10, true))
   263  	require.Nil(t, MaximumNativeType("path", "in", int8(5), 10, true))
   264  	require.Nil(t, MaximumNativeType("path", "in", uint8(5), 10, true))
   265  	require.Nil(t, MaximumNativeType("path", "in", int16(5), 10, true))
   266  	require.Nil(t, MaximumNativeType("path", "in", uint16(5), 10, true))
   267  	require.Nil(t, MaximumNativeType("path", "in", int32(5), 10, true))
   268  	require.Nil(t, MaximumNativeType("path", "in", uint32(5), 10, true))
   269  	require.Nil(t, MaximumNativeType("path", "in", int64(5), 10, true))
   270  	require.Nil(t, MaximumNativeType("path", "in", uint64(5), 10, true))
   271  	require.Nil(t, MaximumNativeType("path", "in", float32(5.5), 10, true))
   272  	require.Nil(t, MaximumNativeType("path", "in", float64(5.5), 10, true))
   273  
   274  	var err *errors.Validation
   275  
   276  	err = MaximumNativeType("path", "in", int32(10), 10, true)
   277  	require.Error(t, err)
   278  	code := int(err.Code())
   279  	assert.Equal(t, errors.MaxFailCode, code)
   280  
   281  	err = MaximumNativeType("path", "in", uint(10), 10, true)
   282  	require.Error(t, err)
   283  	code = int(err.Code())
   284  	assert.Equal(t, errors.MaxFailCode, code)
   285  
   286  	err = MaximumNativeType("path", "in", int64(12), 10, false)
   287  	require.Error(t, err)
   288  	code = int(err.Code())
   289  	assert.Equal(t, errors.MaxFailCode, code)
   290  
   291  	err = MaximumNativeType("path", "in", float32(12.6), 10, false)
   292  	require.Error(t, err)
   293  	code = int(err.Code())
   294  	assert.Equal(t, int(errors.MaxFailCode), code)
   295  
   296  	err = MaximumNativeType("path", "in", float64(12.6), 10, false)
   297  	require.Error(t, err)
   298  	code = int(err.Code())
   299  	assert.Equal(t, int(errors.MaxFailCode), code)
   300  
   301  	err = MaximumNativeType("path", "in", uint(5), -10, true)
   302  	require.Error(t, err)
   303  	code = int(err.Code())
   304  	assert.Equal(t, int(errors.MaxFailCode), code)
   305  }
   306  
   307  // Test edge cases in MinimumNativeType
   308  // not easily exercised with full specs
   309  func TestValues_MinimumNative(t *testing.T) {
   310  	require.Nil(t, MinimumNativeType("path", "in", int(5), 0, false))
   311  	require.Nil(t, MinimumNativeType("path", "in", uint(5), 0, true))
   312  	require.Nil(t, MinimumNativeType("path", "in", int8(5), 0, true))
   313  	require.Nil(t, MinimumNativeType("path", "in", uint8(5), 0, true))
   314  	require.Nil(t, MinimumNativeType("path", "in", int16(5), 0, true))
   315  	require.Nil(t, MinimumNativeType("path", "in", uint16(5), 0, true))
   316  	require.Nil(t, MinimumNativeType("path", "in", int32(5), 0, true))
   317  	require.Nil(t, MinimumNativeType("path", "in", uint32(5), 0, true))
   318  	require.Nil(t, MinimumNativeType("path", "in", int64(5), 0, true))
   319  	require.Nil(t, MinimumNativeType("path", "in", uint64(5), 0, true))
   320  	require.Nil(t, MinimumNativeType("path", "in", float32(5.5), 0, true))
   321  	require.Nil(t, MinimumNativeType("path", "in", float64(5.5), 0, true))
   322  
   323  	var err *errors.Validation
   324  
   325  	err = MinimumNativeType("path", "in", uint(10), 10, true)
   326  	require.Error(t, err)
   327  	code := int(err.Code())
   328  	assert.Equal(t, int(errors.MinFailCode), code)
   329  
   330  	err = MinimumNativeType("path", "in", uint(10), 10, true)
   331  	require.Error(t, err)
   332  	code = int(err.Code())
   333  	assert.Equal(t, int(errors.MinFailCode), code)
   334  
   335  	err = MinimumNativeType("path", "in", int64(8), 10, false)
   336  	require.Error(t, err)
   337  	code = int(err.Code())
   338  	assert.Equal(t, int(errors.MinFailCode), code)
   339  
   340  	err = MinimumNativeType("path", "in", float32(12.6), 20, false)
   341  	require.Error(t, err)
   342  	code = int(err.Code())
   343  	assert.Equal(t, int(errors.MinFailCode), code)
   344  
   345  	err = MinimumNativeType("path", "in", float64(12.6), 20, false)
   346  	require.Error(t, err)
   347  	code = int(err.Code())
   348  	assert.Equal(t, int(errors.MinFailCode), code)
   349  
   350  	require.Nil(t, MinimumNativeType("path", "in", uint(5), -10, true))
   351  }
   352  
   353  // Test edge cases in MaximumNativeType
   354  // not easily exercised with full specs
   355  func TestValues_MultipleOfNative(t *testing.T) {
   356  	require.Nil(t, MultipleOfNativeType("path", "in", int(5), 1))
   357  	require.Nil(t, MultipleOfNativeType("path", "in", uint(5), 1))
   358  	require.Nil(t, MultipleOfNativeType("path", "in", int8(5), 1))
   359  	require.Nil(t, MultipleOfNativeType("path", "in", uint8(5), 1))
   360  	require.Nil(t, MultipleOfNativeType("path", "in", int16(5), 1))
   361  	require.Nil(t, MultipleOfNativeType("path", "in", uint16(5), 1))
   362  	require.Nil(t, MultipleOfNativeType("path", "in", int32(5), 1))
   363  	require.Nil(t, MultipleOfNativeType("path", "in", uint32(5), 1))
   364  	require.Nil(t, MultipleOfNativeType("path", "in", int64(5), 1))
   365  	require.Nil(t, MultipleOfNativeType("path", "in", uint64(5), 1))
   366  
   367  	var err *errors.Validation
   368  
   369  	err = MultipleOfNativeType("path", "in", int64(5), 0)
   370  	require.Error(t, err)
   371  	code := int(err.Code())
   372  	assert.Equal(t, int(errors.MultipleOfMustBePositiveCode), code)
   373  
   374  	err = MultipleOfNativeType("path", "in", uint64(5), 0)
   375  	require.Error(t, err)
   376  	code = int(err.Code())
   377  	assert.Equal(t, int(errors.MultipleOfMustBePositiveCode), code)
   378  
   379  	err = MultipleOfNativeType("path", "in", int64(5), -1)
   380  	require.Error(t, err)
   381  	code = int(err.Code())
   382  	assert.Equal(t, int(errors.MultipleOfMustBePositiveCode), code)
   383  
   384  	err = MultipleOfNativeType("path", "in", int64(11), 5)
   385  	require.Error(t, err)
   386  	code = int(err.Code())
   387  	assert.Equal(t, int(errors.MultipleOfFailCode), code)
   388  
   389  	err = MultipleOfNativeType("path", "in", uint64(11), 5)
   390  	require.Error(t, err)
   391  	code = int(err.Code())
   392  	assert.Equal(t, int(errors.MultipleOfFailCode), code)
   393  }
   394  
   395  // Test edge cases in IsValueValidAgainstRange
   396  // not easily exercised with full specs: we did not simulate these formats in full specs
   397  func TestValues_IsValueValidAgainstRange(t *testing.T) {
   398  	require.NoError(t, IsValueValidAgainstRange(float32(123.45), "number", "float32", "prefix", "path"))
   399  	require.NoError(t, IsValueValidAgainstRange(float64(123.45), "number", "float32", "prefix", "path"))
   400  	require.NoError(t, IsValueValidAgainstRange(int64(123), "number", "float", "prefix", "path"))
   401  	require.NoError(t, IsValueValidAgainstRange(int64(123), "integer", "", "prefix", "path"))
   402  	require.NoError(t, IsValueValidAgainstRange(int64(123), "integer", "int64", "prefix", "path"))
   403  	require.NoError(t, IsValueValidAgainstRange(int64(123), "integer", "uint64", "prefix", "path"))
   404  	require.NoError(t, IsValueValidAgainstRange(int64(2147483647), "integer", "int32", "prefix", "path"))
   405  	require.NoError(t, IsValueValidAgainstRange(int64(2147483647), "integer", "uint32", "prefix", "path"))
   406  
   407  	var err error
   408  	// Error case (do not occur in normal course of a validation)
   409  	err = IsValueValidAgainstRange(float64(math.MaxFloat64), "integer", "", "prefix", "path")
   410  	require.Error(t, err)
   411  	assert.Contains(t, err.Error(), "must be of type integer (default format)")
   412  
   413  	// Checking a few limits
   414  	err = IsValueValidAgainstRange("123", "number", "", "prefix", "path")
   415  	require.Error(t, err)
   416  	assert.Contains(t, err.Error(), "called with invalid (non numeric) val type")
   417  }
   418  

View as plain text