Files
fn-serverless/vendor/github.com/go-openapi/validate/items_validator_test.go
2017-06-11 02:05:36 -07:00

518 lines
14 KiB
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 (
"encoding/json"
"fmt"
"testing"
"github.com/go-openapi/errors"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
"github.com/stretchr/testify/assert"
)
type email struct {
Address string
}
type paramFactory func(string) *spec.Parameter
var paramFactories = []paramFactory{
spec.QueryParam,
spec.HeaderParam,
spec.PathParam,
spec.FormDataParam,
}
var stringItems = new(spec.Items)
func init() {
stringItems.Type = "string"
}
func requiredError(param *spec.Parameter) *errors.Validation {
return errors.Required(param.Name, param.In)
}
func maxErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.ExceedsMaximum(path, in, *items.Maximum, items.ExclusiveMaximum)
}
func minErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.ExceedsMinimum(path, in, *items.Minimum, items.ExclusiveMinimum)
}
func multipleOfErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.NotMultipleOf(path, in, *items.MultipleOf)
}
func requiredErrorItems(path, in string) *errors.Validation {
return errors.Required(path, in)
}
func maxLengthErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.TooLong(path, in, *items.MaxLength)
}
func minLengthErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.TooShort(path, in, *items.MinLength)
}
func patternFailItems(path, in string, items *spec.Items) *errors.Validation {
return errors.FailedPattern(path, in, items.Pattern)
}
func enumFailItems(path, in string, items *spec.Items, data interface{}) *errors.Validation {
return errors.EnumFail(path, in, data, items.Enum)
}
func minItemsErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.TooFewItems(path, in, *items.MinItems)
}
func maxItemsErrorItems(path, in string, items *spec.Items) *errors.Validation {
return errors.TooManyItems(path, in, *items.MaxItems)
}
func duplicatesErrorItems(path, in string) *errors.Validation {
return errors.DuplicateItems(path, in)
}
func TestNumberItemsValidation(t *testing.T) {
values := [][]interface{}{
[]interface{}{23, 49, 56, 21, 14, 35, 28, 7, 42},
[]interface{}{uint(23), uint(49), uint(56), uint(21), uint(14), uint(35), uint(28), uint(7), uint(42)},
[]interface{}{float64(23), float64(49), float64(56), float64(21), float64(14), float64(35), float64(28), float64(7), float64(42)},
}
for i, v := range values {
items := spec.NewItems()
items.WithMaximum(makeFloat(v[1]), false)
items.WithMinimum(makeFloat(v[3]), false)
items.WithMultipleOf(makeFloat(v[7]))
items.WithEnum(v[3], v[6], v[8], v[1])
items.Typed("integer", "int32")
parent := spec.QueryParam("factors").CollectionOf(items, "")
path := fmt.Sprintf("factors.%d", i)
validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default)
// MultipleOf
err := validator.Validate(i, v[0])
assert.True(t, err.HasErrors())
assert.EqualError(t, multipleOfErrorItems(path, validator.in, items), err.Errors[0].Error())
// Maximum
err = validator.Validate(i, v[1])
assert.True(t, err == nil || err.IsValid())
err = validator.Validate(i, v[2])
assert.True(t, err.HasErrors())
assert.EqualError(t, maxErrorItems(path, validator.in, items), err.Errors[0].Error())
// ExclusiveMaximum
items.ExclusiveMaximum = true
// requires a new items validator because this is set a creation time
validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default)
err = validator.Validate(i, v[1])
assert.True(t, err.HasErrors())
assert.EqualError(t, maxErrorItems(path, validator.in, items), err.Errors[0].Error())
// Minimum
err = validator.Validate(i, v[3])
assert.True(t, err == nil || err.IsValid())
err = validator.Validate(i, v[4])
assert.True(t, err.HasErrors())
assert.EqualError(t, minErrorItems(path, validator.in, items), err.Errors[0].Error())
// ExclusiveMinimum
items.ExclusiveMinimum = true
// requires a new items validator because this is set a creation time
validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default)
err = validator.Validate(i, v[3])
assert.True(t, err.HasErrors())
assert.EqualError(t, minErrorItems(path, validator.in, items), err.Errors[0].Error())
// Enum
err = validator.Validate(i, v[5])
assert.True(t, err.HasErrors())
assert.EqualError(t, enumFailItems(path, validator.in, items, v[5]), err.Errors[0].Error())
// Valid passes
err = validator.Validate(i, v[6])
assert.True(t, err == nil || err.IsValid())
}
}
func TestStringItemsValidation(t *testing.T) {
items := spec.NewItems().WithMinLength(3).WithMaxLength(5).WithPattern(`^[a-z]+$`).Typed("string", "")
items.WithEnum("aaa", "bbb", "ccc")
parent := spec.QueryParam("tags").CollectionOf(items, "")
path := parent.Name + ".1"
validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default)
// required
err := validator.Validate(1, "")
assert.True(t, err.HasErrors())
assert.EqualError(t, minLengthErrorItems(path, validator.in, items), err.Errors[0].Error())
// MaxLength
err = validator.Validate(1, "abcdef")
assert.True(t, err.HasErrors())
assert.EqualError(t, maxLengthErrorItems(path, validator.in, items), err.Errors[0].Error())
// MinLength
err = validator.Validate(1, "a")
assert.True(t, err.HasErrors())
assert.EqualError(t, minLengthErrorItems(path, validator.in, items), err.Errors[0].Error())
// Pattern
err = validator.Validate(1, "a394")
assert.True(t, err.HasErrors())
assert.EqualError(t, patternFailItems(path, validator.in, items), err.Errors[0].Error())
// Enum
err = validator.Validate(1, "abcde")
assert.True(t, err.HasErrors())
assert.EqualError(t, enumFailItems(path, validator.in, items, "abcde"), err.Errors[0].Error())
// Valid passes
err = validator.Validate(1, "bbb")
assert.True(t, err == nil || err.IsValid())
}
func TestArrayItemsValidation(t *testing.T) {
items := spec.NewItems().CollectionOf(stringItems, "").WithMinItems(1).WithMaxItems(5).UniqueValues()
items.WithEnum("aaa", "bbb", "ccc")
parent := spec.QueryParam("tags").CollectionOf(items, "")
path := parent.Name + ".1"
validator := newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default)
// MinItems
err := validator.Validate(1, []string{})
assert.True(t, err.HasErrors())
assert.EqualError(t, minItemsErrorItems(path, validator.in, items), err.Errors[0].Error())
// MaxItems
err = validator.Validate(1, []string{"a", "b", "c", "d", "e", "f"})
assert.True(t, err.HasErrors())
assert.EqualError(t, maxItemsErrorItems(path, validator.in, items), err.Errors[0].Error())
// UniqueItems
err = validator.Validate(1, []string{"a", "a"})
assert.True(t, err.HasErrors())
assert.EqualError(t, duplicatesErrorItems(path, validator.in), err.Errors[0].Error())
// Enum
err = validator.Validate(1, []string{"a", "b", "c"})
assert.True(t, err.HasErrors())
assert.EqualError(t, enumFailItems(path, validator.in, items, []string{"a", "b", "c"}), err.Errors[0].Error())
// Items
strItems := spec.NewItems().WithMinLength(3).WithMaxLength(5).WithPattern(`^[a-z]+$`).Typed("string", "")
items = spec.NewItems().CollectionOf(strItems, "").WithMinItems(1).WithMaxItems(5).UniqueValues()
validator = newItemsValidator(parent.Name, parent.In, items, parent, strfmt.Default)
err = validator.Validate(1, []string{"aa", "bbb", "ccc"})
assert.True(t, err.HasErrors())
assert.EqualError(t, minLengthErrorItems(path+".0", parent.In, strItems), err.Errors[0].Error())
}
// PetStoreJSONMessage json raw message for Petstore20
var PetStoreJSONMessage = json.RawMessage([]byte(PetStore20))
// PetStore20 json doc for swagger 2.0 pet store
const PetStore20 = `{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"contact": {
"name": "Wordnik API Team",
"url": "http://developer.wordnik.com"
},
"license": {
"name": "Creative Commons 4.0 International",
"url": "http://creativecommons.org/licenses/by/4.0/"
}
},
"host": "petstore.swagger.wordnik.com",
"basePath": "/api",
"schemes": [
"http"
],
"paths": {
"/pets": {
"get": {
"security": [
{
"basic": []
}
],
"tags": [ "Pet Operations" ],
"operationId": "getAllPets",
"parameters": [
{
"name": "status",
"in": "query",
"description": "The status to filter by",
"type": "string"
},
{
"name": "limit",
"in": "query",
"description": "The maximum number of results to return",
"type": "integer",
"format": "int64"
}
],
"summary": "Finds all pets in the system",
"responses": {
"200": {
"description": "Pet response",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"default": {
"description": "Unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"post": {
"security": [
{
"basic": []
}
],
"tags": [ "Pet Operations" ],
"operationId": "createPet",
"summary": "Creates a new pet",
"consumes": ["application/x-yaml"],
"produces": ["application/x-yaml"],
"parameters": [
{
"name": "pet",
"in": "body",
"description": "The Pet to create",
"required": true,
"schema": {
"$ref": "#/definitions/newPet"
}
}
],
"responses": {
"200": {
"description": "Created Pet response",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"default": {
"description": "Unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
}
},
"/pets/{id}": {
"delete": {
"security": [
{
"apiKey": []
}
],
"description": "Deletes the Pet by id",
"operationId": "deletePet",
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of pet to delete",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"204": {
"description": "pet deleted"
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"get": {
"tags": [ "Pet Operations" ],
"operationId": "getPetById",
"summary": "Finds the pet by id",
"responses": {
"200": {
"description": "Pet response",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"default": {
"description": "Unexpected error",
"schema": {
"$ref": "#/definitions/Error"
}
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of pet",
"required": true,
"type": "integer",
"format": "int64"
}
]
}
},
"definitions": {
"Category": {
"id": "Category",
"properties": {
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
}
}
},
"Pet": {
"id": "Pet",
"properties": {
"category": {
"$ref": "#/definitions/Category"
},
"id": {
"description": "unique identifier for the pet",
"format": "int64",
"maximum": 100.0,
"minimum": 0.0,
"type": "integer"
},
"name": {
"type": "string"
},
"photoUrls": {
"items": {
"type": "string"
},
"type": "array"
},
"status": {
"description": "pet status in the store",
"enum": [
"available",
"pending",
"sold"
],
"type": "string"
},
"tags": {
"items": {
"$ref": "#/definitions/Tag"
},
"type": "array"
}
},
"required": [
"id",
"name"
]
},
"newPet": {
"anyOf": [
{
"$ref": "#/definitions/Pet"
},
{
"required": [
"name"
]
}
]
},
"Tag": {
"id": "Tag",
"properties": {
"id": {
"format": "int64",
"type": "integer"
},
"name": {
"type": "string"
}
}
},
"Error": {
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
},
"consumes": [
"application/json",
"application/xml"
],
"produces": [
"application/json",
"application/xml",
"text/plain",
"text/html"
],
"securityDefinitions": {
"basic": {
"type": "basic"
},
"apiKey": {
"type": "apiKey",
"in": "header",
"name": "X-API-KEY"
}
}
}
`