...

Source file src/github.com/go-openapi/validate/items_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  	"encoding/json"
    19  	"fmt"
    20  	"log"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	"github.com/go-openapi/errors"
    26  	"github.com/go-openapi/spec"
    27  	"github.com/go-openapi/strfmt"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  var (
    33  	// PetStore20 json doc for swagger 2.0 pet store
    34  	PetStore20 string
    35  
    36  	// PetStoreJSONMessage json raw message for Petstore20
    37  	PetStoreJSONMessage json.RawMessage
    38  )
    39  
    40  func init() {
    41  	petstoreFixture := filepath.Join("fixtures", "petstore", "swagger.json")
    42  	petstore, err := os.ReadFile(petstoreFixture)
    43  	if err != nil {
    44  		log.Fatalf("could not initialize fixture: %s: %v", petstoreFixture, err)
    45  	}
    46  	PetStoreJSONMessage = json.RawMessage(petstore)
    47  	PetStore20 = string(petstore)
    48  }
    49  
    50  func stringItems() *spec.Items {
    51  	return spec.NewItems().Typed(stringType, "")
    52  }
    53  
    54  func requiredError(param *spec.Parameter, data interface{}) *errors.Validation {
    55  	return errors.Required(param.Name, param.In, data)
    56  }
    57  
    58  func maxErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    59  	return errors.ExceedsMaximum(path, in, *items.Maximum, items.ExclusiveMaximum, data)
    60  }
    61  
    62  func minErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    63  	return errors.ExceedsMinimum(path, in, *items.Minimum, items.ExclusiveMinimum, data)
    64  }
    65  
    66  func multipleOfErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    67  	return errors.NotMultipleOf(path, in, *items.MultipleOf, data)
    68  }
    69  
    70  /*
    71  func requiredErrorItems(path, in string) *errors.Validation {
    72  	return errors.Required(path, in)
    73  }
    74  */
    75  
    76  func maxLengthErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    77  	return errors.TooLong(path, in, *items.MaxLength, data)
    78  }
    79  
    80  func minLengthErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    81  	return errors.TooShort(path, in, *items.MinLength, data)
    82  }
    83  
    84  func patternFailItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    85  	return errors.FailedPattern(path, in, items.Pattern, data)
    86  }
    87  
    88  func enumFailItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    89  	return errors.EnumFail(path, in, data, items.Enum)
    90  }
    91  
    92  func minItemsErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    93  	return errors.TooFewItems(path, in, *items.MinItems, data)
    94  }
    95  
    96  func maxItemsErrorItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
    97  	return errors.TooManyItems(path, in, *items.MaxItems, data)
    98  }
    99  
   100  func duplicatesErrorItems(path, in string) *errors.Validation {
   101  	return errors.DuplicateItems(path, in)
   102  }
   103  
   104  func TestNumberItemsValidation(t *testing.T) {
   105  
   106  	values := [][]interface{}{
   107  		{23, 49, 56, 21, 14, 35, 28, 7, 42},
   108  		{uint(23), uint(49), uint(56), uint(21), uint(14), uint(35), uint(28), uint(7), uint(42)},
   109  		{float64(23), float64(49), float64(56), float64(21), float64(14), float64(35), float64(28), float64(7), float64(42)},
   110  	}
   111  
   112  	for i, v := range values {
   113  		items := spec.NewItems()
   114  		items.WithMaximum(makeFloat(v[1]), false)
   115  		items.WithMinimum(makeFloat(v[3]), false)
   116  		items.WithMultipleOf(makeFloat(v[7]))
   117  		items.WithEnum(v[3], v[6], v[8], v[1])
   118  		items.Typed("integer", "int32")
   119  		parent := spec.QueryParam("factors").CollectionOf(items, "")
   120  		path := fmt.Sprintf("factors.%d", i)
   121  		validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
   122  
   123  		// MultipleOf
   124  		err := validator.Validate(i, v[0])
   125  		assert.True(t, err.HasErrors())
   126  		require.NotEmpty(t, err.Errors)
   127  		require.EqualError(t, multipleOfErrorItems(path, validator.in, items, v[0]), err.Errors[0].Error())
   128  
   129  		// Maximum
   130  		err = validator.Validate(i, v[1])
   131  		assert.True(t, err == nil || err.IsValid())
   132  		err = validator.Validate(i, v[2])
   133  		assert.True(t, err.HasErrors())
   134  		require.NotEmpty(t, err.Errors)
   135  		require.EqualError(t, maxErrorItems(path, validator.in, items, v[2]), err.Errors[0].Error())
   136  
   137  		// ExclusiveMaximum
   138  		items.ExclusiveMaximum = true
   139  		// requires a new items validator because this is set a creation time
   140  		validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
   141  		err = validator.Validate(i, v[1])
   142  		assert.True(t, err.HasErrors())
   143  		require.NotEmpty(t, err.Errors)
   144  		require.EqualError(t, maxErrorItems(path, validator.in, items, v[1]), err.Errors[0].Error())
   145  
   146  		// Minimum
   147  		err = validator.Validate(i, v[3])
   148  		assert.True(t, err == nil || err.IsValid())
   149  		err = validator.Validate(i, v[4])
   150  		assert.True(t, err.HasErrors())
   151  		require.NotEmpty(t, err.Errors)
   152  		require.EqualError(t, minErrorItems(path, validator.in, items, v[4]), err.Errors[0].Error())
   153  
   154  		// ExclusiveMinimum
   155  		items.ExclusiveMinimum = true
   156  		// requires a new items validator because this is set a creation time
   157  		validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
   158  		err = validator.Validate(i, v[3])
   159  		assert.True(t, err.HasErrors())
   160  		require.NotEmpty(t, err.Errors)
   161  		require.EqualError(t, minErrorItems(path, validator.in, items, v[3]), err.Errors[0].Error())
   162  
   163  		// Enum
   164  		err = validator.Validate(i, v[5])
   165  		assert.True(t, err.HasErrors())
   166  		require.NotEmpty(t, err.Errors)
   167  		require.EqualError(t, enumFailItems(path, validator.in, items, v[5]), err.Errors[0].Error())
   168  
   169  		// Valid passes
   170  		err = validator.Validate(i, v[6])
   171  		assert.True(t, err == nil || err.IsValid())
   172  	}
   173  
   174  }
   175  
   176  func TestStringItemsValidation(t *testing.T) {
   177  	items := spec.NewItems().WithMinLength(3).WithMaxLength(5).WithPattern(`^[a-z]+$`).Typed(stringType, "")
   178  	items.WithEnum("aaa", "bbb", "ccc")
   179  	parent := spec.QueryParam("tags").CollectionOf(items, "")
   180  	path := parent.Name + ".1"
   181  	validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
   182  
   183  	// required
   184  	data := ""
   185  	err := validator.Validate(1, data)
   186  	assert.True(t, err.HasErrors())
   187  	require.NotEmpty(t, err.Errors)
   188  	require.EqualError(t, minLengthErrorItems(path, validator.in, items, data), err.Errors[0].Error())
   189  
   190  	// MaxLength
   191  	data = "abcdef"
   192  	err = validator.Validate(1, data)
   193  	assert.True(t, err.HasErrors())
   194  	require.NotEmpty(t, err.Errors)
   195  	require.EqualError(t, maxLengthErrorItems(path, validator.in, items, data), err.Errors[0].Error())
   196  
   197  	// MinLength
   198  	data = "a"
   199  	err = validator.Validate(1, data)
   200  	assert.True(t, err.HasErrors())
   201  	require.NotEmpty(t, err.Errors)
   202  	require.EqualError(t, minLengthErrorItems(path, validator.in, items, data), err.Errors[0].Error())
   203  
   204  	// Pattern
   205  	data = "a394"
   206  	err = validator.Validate(1, data)
   207  	assert.True(t, err.HasErrors())
   208  	require.NotEmpty(t, err.Errors)
   209  	require.EqualError(t, patternFailItems(path, validator.in, items, data), err.Errors[0].Error())
   210  
   211  	// Enum
   212  	data = "abcde"
   213  	err = validator.Validate(1, data)
   214  	assert.True(t, err.HasErrors())
   215  	require.NotEmpty(t, err.Errors)
   216  	require.EqualError(t, enumFailItems(path, validator.in, items, data), err.Errors[0].Error())
   217  
   218  	// Valid passes
   219  	err = validator.Validate(1, "bbb")
   220  	assert.True(t, err == nil || err.IsValid())
   221  }
   222  
   223  func TestArrayItemsValidation(t *testing.T) {
   224  	items := spec.NewItems().CollectionOf(stringItems(), "").WithMinItems(1).WithMaxItems(5).UniqueValues()
   225  	items.WithEnum("aaa", "bbb", "ccc")
   226  	parent := spec.QueryParam("tags").CollectionOf(items, "")
   227  	path := parent.Name + ".1"
   228  	validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
   229  
   230  	// MinItems
   231  	data := []string{}
   232  	err := validator.Validate(1, data)
   233  	assert.True(t, err.HasErrors())
   234  	require.NotEmpty(t, err.Errors)
   235  	require.EqualError(t, minItemsErrorItems(path, validator.in, items, len(data)), err.Errors[0].Error())
   236  	// MaxItems
   237  	data = []string{"a", "b", "c", "d", "e", "f"}
   238  	err = validator.Validate(1, data)
   239  	assert.True(t, err.HasErrors())
   240  	require.NotEmpty(t, err.Errors)
   241  	require.EqualError(t, maxItemsErrorItems(path, validator.in, items, len(data)), err.Errors[0].Error())
   242  	// UniqueItems
   243  	err = validator.Validate(1, []string{"a", "a"})
   244  	assert.True(t, err.HasErrors())
   245  	require.NotEmpty(t, err.Errors)
   246  	require.EqualError(t, duplicatesErrorItems(path, validator.in), err.Errors[0].Error())
   247  
   248  	// Enum
   249  	data = []string{"a", "b", "c"}
   250  	err = validator.Validate(1, data)
   251  	assert.True(t, err.HasErrors())
   252  	require.NotEmpty(t, err.Errors)
   253  	require.EqualError(t, enumFailItems(path, validator.in, items, data), err.Errors[0].Error())
   254  
   255  	// Items
   256  	strItems := spec.NewItems().WithMinLength(3).WithMaxLength(5).WithPattern(`^[a-z]+$`).Typed(stringType, "")
   257  	items = spec.NewItems().CollectionOf(strItems, "").WithMinItems(1).WithMaxItems(5).UniqueValues()
   258  	validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default, nil)
   259  
   260  	data = []string{"aa", "bbb", "ccc"}
   261  	err = validator.Validate(1, data)
   262  	assert.True(t, err.HasErrors())
   263  	require.NotEmpty(t, err.Errors)
   264  	require.EqualError(t, minLengthErrorItems(path+".0", parent.In, strItems, data[0]), err.Errors[0].Error())
   265  }
   266  

View as plain text