Skip to content
Snippets Groups Projects
Commit 66a900ef authored by Guillem Jover's avatar Guillem Jover
Browse files

New upstream version 0.20.1

parents b2b2befa 8b5b7790
No related branches found
No related tags found
No related merge requests found
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
gocyclo:
min-complexity: 30
maligned:
suggest-new: true
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 4
linters:
enable-all: true
disable:
- maligned
- lll
- gochecknoglobals
- godox
- gocognit
- whitespace
- wsl
- funlen
- gochecknoglobals
- gochecknoinits
- scopelint
- wrapcheck
- exhaustivestruct
- exhaustive
- nlreturn
- testpackage
- gci
- gofumpt
- goerr113
- gomnd
- tparallel
- nestif
- godot
- errorlint
- paralleltest
- tparallel
language: go
go:
- 1.7
install:
- go get -u github.com/stretchr/testify/assert
script:
- go test -v -race -cover -coverprofile=coverage.txt -covermode=atomic ./...
after_success:
- bash <(curl -s https://codecov.io/bash)
go:
- 1.14.x
- 1.x
arch:
- amd64
jobs:
include:
# only run fast tests on ppc64le
- go: 1.x
arch: ppc64le
script:
- gotestsum -f short-verbose -- ./...
# include linting job, but only for latest go version and amd64 arch
- go: 1.x
arch: amd64
install:
go get github.com/golangci/golangci-lint/cmd/golangci-lint
script:
- golangci-lint run --new-from-rev master
install:
- GO111MODULE=off go get -u gotest.tools/gotestsum
language: go
notifications:
slack:
secure: gZGp9NaHxi7zawlXJXKY92BGeDR1x0tbIcTyU5nMKLq0fhIaiEBJEeALwZ4VgqsSv3DytSSF5mLH8fevAM3ixE6hxjKQ+lQuf7V/w3btCN1CSWgoua5LOh1kTnqZQtJuRvO4pzoJcT3bJWBsVZ07VGNVzzJEy/zAKCHFqBUCXShw7QemlLBcYWFNqveTlvDIfCzvouoLnPoXwxEpkjxe9uz/ZKZgAnup/fXjC8RFctmgCnkCyvJTk0Y/fZCsufixJrJhshBWTnlrFCzRmgNkz2d+i1Ls3+MJ5EJJ2Tx/A5S63dL49J1f9Kr0AKHADmulSy8JNzIckKwbyFMYUecrsW+Lsu9DhnVMy1jj5pKsJDLRi2iIU3fXTMWbcyQbXjbbnBO2mPdP3Tzme75y4D9fc8hUPeyqVv2BU26NEbQ7EF2pKJ93OXvci7HlwRBgdJa8j6mP2LEDClcPQW00g7N/OZe0cTOMa8L5AwiBlbArwqt9wv6YLJoTG0wpDhzWsFvbCg5bJxe28Yn3fIDD0Lk1I7iSnBbp/5gzF19jmxqvcT8tHRkDL4xfjbENFTZjA5uB4Z4pj4WSyWQILLV/Jwhe3fi9uQwdviFHfj5pnVrmNUiGSOQL672K5wl2c3E9mGwejvsu2dfEz28n7Y/FUnOpY3/cBS0n27JJaerS0zMKNLE=
script:
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...
# OpenAPI errors [![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors) [![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
# OpenAPI errors
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/errors?status.svg)](http://godoc.org/github.com/go-openapi/errors)
[![Build Status](https://travis-ci.org/go-openapi/errors.svg?branch=master)](https://travis-ci.org/go-openapi/errors)
[![codecov](https://codecov.io/gh/go-openapi/errors/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/errors)
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/errors/master/LICENSE)
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/errors.svg)](https://pkg.go.dev/github.com/go-openapi/errors)
[![GolangCI](https://golangci.com/badges/github.com/go-openapi/errors.svg)](https://golangci.com)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/errors)](https://goreportcard.com/report/github.com/go-openapi/errors)
Shared errors used throughout the various libraries for the go-openapi toolkit
\ No newline at end of file
Shared errors and error interface used throughout the various libraries found in the go-openapi toolkit.
......@@ -18,9 +18,13 @@ import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"strings"
)
// DefaultHTTPCode is used when the error Code cannot be used as an HTTP code.
var DefaultHTTPCode = http.StatusUnprocessableEntity
// Error represents a error interface all swagger framework errors implement
type Error interface {
error
......@@ -40,6 +44,14 @@ func (a *apiError) Code() int32 {
return a.code
}
// MarshalJSON implements the JSON encoding interface
func (a apiError) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": a.code,
"message": a.message,
})
}
// New creates a new API error with a code and a message
func New(code int32, message string, args ...interface{}) Error {
if len(args) > 0 {
......@@ -77,6 +89,15 @@ func (m *MethodNotAllowedError) Code() int32 {
return m.code
}
// MarshalJSON implements the JSON encoding interface
func (m MethodNotAllowedError) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": m.code,
"message": m.message,
"allowed": m.Allowed,
})
}
func errorAsJSON(err Error) []byte {
b, _ := json.Marshal(struct {
Code int32 `json:"code"`
......@@ -111,8 +132,6 @@ func MethodNotAllowed(requested string, allow []string) Error {
return &MethodNotAllowedError{code: http.StatusMethodNotAllowed, Allowed: allow, message: msg}
}
const head = "HEAD"
// ServeError the error handler interface implementation
func ServeError(rw http.ResponseWriter, r *http.Request, err error) {
rw.Header().Set("Content-Type", "application/json")
......@@ -129,33 +148,34 @@ func ServeError(rw http.ResponseWriter, r *http.Request, err error) {
case *MethodNotAllowedError:
rw.Header().Add("Allow", strings.Join(err.(*MethodNotAllowedError).Allowed, ","))
rw.WriteHeader(asHTTPCode(int(e.Code())))
if r == nil || r.Method != head {
rw.Write(errorAsJSON(e))
if r == nil || r.Method != http.MethodHead {
_, _ = rw.Write(errorAsJSON(e))
}
case Error:
if e == nil {
value := reflect.ValueOf(e)
if value.Kind() == reflect.Ptr && value.IsNil() {
rw.WriteHeader(http.StatusInternalServerError)
rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
_, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
return
}
rw.WriteHeader(asHTTPCode(int(e.Code())))
if r == nil || r.Method != head {
rw.Write(errorAsJSON(e))
if r == nil || r.Method != http.MethodHead {
_, _ = rw.Write(errorAsJSON(e))
}
case nil:
rw.WriteHeader(http.StatusInternalServerError)
rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
_, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, "Unknown error")))
default:
rw.WriteHeader(http.StatusInternalServerError)
if r == nil || r.Method != head {
rw.Write(errorAsJSON(New(http.StatusInternalServerError, err.Error())))
if r == nil || r.Method != http.MethodHead {
_, _ = rw.Write(errorAsJSON(New(http.StatusInternalServerError, err.Error())))
}
}
}
func asHTTPCode(input int) int {
if input >= 600 {
return 422
return DefaultHTTPCode
}
return input
}
......@@ -18,11 +18,17 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type customError struct {
apiError
}
func TestServeError(t *testing.T) {
// method not allowed wins
// err abides by the Error interface
......@@ -50,6 +56,20 @@ func TestServeError(t *testing.T) {
// assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
assert.Equal(t, `{"code":601,"message":"someType is an invalid type name"}`, recorder.Body.String())
// same, but override DefaultHTTPCode
func() {
oldDefaultHTTPCode := DefaultHTTPCode
defer func() { DefaultHTTPCode = oldDefaultHTTPCode }()
DefaultHTTPCode = http.StatusBadRequest
err = InvalidTypeName("someType")
recorder = httptest.NewRecorder()
ServeError(recorder, nil, err)
assert.Equal(t, http.StatusBadRequest, recorder.Code)
// assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
assert.Equal(t, `{"code":601,"message":"someType is an invalid type name"}`, recorder.Body.String())
}()
// defaults to internal server error
simpleErr := fmt.Errorf("some error")
recorder = httptest.NewRecorder()
......@@ -118,6 +138,12 @@ func TestServeError(t *testing.T) {
ServeError(recorder, nil, nil)
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
assert.Equal(t, `{"code":500,"message":"Unknown error"}`, recorder.Body.String())
recorder = httptest.NewRecorder()
var z *customError
ServeError(recorder, nil, z)
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
assert.Equal(t, `{"code":500,"message":"Unknown error"}`, recorder.Body.String())
}
func TestAPIErrors(t *testing.T) {
......@@ -182,3 +208,44 @@ func TestValidateName(t *testing.T) {
assert.EqualValues(t, "myNewName", vv.Name)
assert.EqualValues(t, "myNewNamemyMessage", vv.message)
}
func TestMarshalJSON(t *testing.T) {
const (
expectedCode = http.StatusUnsupportedMediaType
value = "myValue"
)
list := []string{"a", "b"}
e := InvalidContentType(value, list)
jazon, err := e.MarshalJSON()
require.NoError(t, err)
expectedMessage := strings.ReplaceAll(fmt.Sprintf(contentTypeFail, value, list), `"`, `\"`)
expectedJSON := fmt.Sprintf(
`{"code":%d,"message":"%s","name":"Content-Type","in":"header","value":"%s","values":["a","b"]}`,
expectedCode, expectedMessage, value,
)
assert.JSONEq(t, expectedJSON, string(jazon))
a := apiError{code: 1, message: "a"}
jazon, err = a.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"code":1,"message":"a"}`, string(jazon))
m := MethodNotAllowedError{code: 1, message: "a", Allowed: []string{"POST"}}
jazon, err = m.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"code":1,"message":"a","allowed":["POST"]}`, string(jazon))
c := CompositeError{Errors: []error{e}, code: 1, message: "a"}
jazon, err = c.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, fmt.Sprintf(`{"code":1,"message":"a","errors":[%s]}`, expectedJSON), string(jazon))
p := ParseError{code: 1, message: "x", Name: "a", In: "b", Value: "c", Reason: fmt.Errorf("d")}
jazon, err = p.MarshalJSON()
require.NoError(t, err)
assert.JSONEq(t, `{"code":1,"message":"x","name":"a","in":"b","value":"c","reason":"d"}`, string(jazon))
}
......@@ -14,7 +14,9 @@
package errors
import "net/http"
// Unauthenticated returns an unauthenticated error
func Unauthenticated(scheme string) Error {
return New(401, "unauthenticated for %s", scheme)
return New(http.StatusUnauthorized, "unauthenticated for %s", scheme)
}
go.mod 0 → 100644
module github.com/go-openapi/errors
go 1.14
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/stretchr/testify v1.6.1
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c // indirect
)
go.sum 0 → 100644
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
......@@ -15,6 +15,7 @@
package errors
import (
"encoding/json"
"fmt"
"net/http"
)
......@@ -38,11 +39,28 @@ func (e *Validation) Code() int32 {
return e.code
}
// ValidateName produces an error message name for an aliased property
// MarshalJSON implements the JSON encoding interface
func (e Validation) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": e.code,
"message": e.message,
"in": e.In,
"name": e.Name,
"value": e.Value,
"values": e.Values,
})
}
// ValidateName sets the name for a validation or updates it for a nested property
func (e *Validation) ValidateName(name string) *Validation {
if e.Name == "" && name != "" {
e.Name = name
e.message = name + e.message
if name != "" {
if e.Name == "" {
e.Name = name
e.message = name + e.message
} else {
e.Name = name + "." + e.Name
e.message = name + "." + e.message
}
}
return e
}
......@@ -54,7 +72,7 @@ const (
// InvalidContentType error for an invalid content type
func InvalidContentType(value string, allowed []string) *Validation {
var values []interface{}
values := make([]interface{}, 0, len(allowed))
for _, v := range allowed {
values = append(values, v)
}
......@@ -70,7 +88,7 @@ func InvalidContentType(value string, allowed []string) *Validation {
// InvalidResponseFormat error for an unacceptable response format request
func InvalidResponseFormat(value string, allowed []string) *Validation {
var values []interface{}
values := make([]interface{}, 0, len(allowed))
for _, v := range allowed {
values = append(values, v)
}
......
......@@ -23,9 +23,9 @@ import (
// APIVerificationFailed is an error that contains all the missing info for a mismatched section
// between the api registrations and the api spec
type APIVerificationFailed struct {
Section string
MissingSpecification []string
MissingRegistration []string
Section string `json:"section,omitempty"`
MissingSpecification []string `json:"missingSpecification,omitempty"`
MissingRegistration []string `json:"missingRegistration,omitempty"`
}
//
......
......@@ -14,9 +14,12 @@
package errors
import "fmt"
import (
"encoding/json"
"fmt"
)
// ParseError respresents a parsing error
// ParseError represents a parsing error
type ParseError struct {
code int32
Name string
......@@ -35,6 +38,22 @@ func (e *ParseError) Code() int32 {
return e.code
}
// MarshalJSON implements the JSON encoding interface
func (e ParseError) MarshalJSON() ([]byte, error) {
var reason string
if e.Reason != nil {
reason = e.Reason.Error()
}
return json.Marshal(map[string]interface{}{
"code": e.code,
"message": e.message,
"in": e.In,
"name": e.Name,
"value": e.Value,
"reason": reason,
})
}
const (
parseErrorTemplContent = `parsing %s %s from %q failed, because %s`
parseErrorTemplContentNoIn = `parsing %s from %q failed, because %s`
......
......@@ -15,6 +15,7 @@
package errors
import (
"encoding/json"
"fmt"
"strings"
)
......@@ -25,6 +26,7 @@ const (
typeFailWithData = "%s in %s must be of type %s: %q"
typeFailWithError = "%s in %s must be of type %s, because: %s"
requiredFail = "%s in %s is required"
readOnlyFail = "%s in %s is readOnly"
tooLongMessage = "%s in %s should be at most %d chars long"
tooShortMessage = "%s in %s should be at least %d chars long"
patternFail = "%s in %s should match '%s'"
......@@ -41,6 +43,7 @@ const (
typeFailWithDataNoIn = "%s must be of type %s: %q"
typeFailWithErrorNoIn = "%s must be of type %s, because: %s"
requiredFailNoIn = "%s is required"
readOnlyFailNoIn = "%s is readOnly"
tooLongMessageNoIn = "%s should be at most %d chars long"
tooShortMessageNoIn = "%s should be at least %d chars long"
patternFailNoIn = "%s should match '%s'"
......@@ -91,6 +94,7 @@ const (
UnallowedPropertyCode
FailedAllPatternPropsCode
MultipleOfMustBePositiveCode
ReadOnlyFailCode
)
// CompositeError is an error that groups several errors together
......@@ -116,6 +120,15 @@ func (c *CompositeError) Error() string {
return c.message
}
// MarshalJSON implements the JSON encoding interface
func (c CompositeError) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"code": c.code,
"message": c.message,
"errors": c.Errors,
})
}
// CompositeValidationError an error to wrap a bunch of other errors
func CompositeValidationError(errors ...error) *CompositeError {
return &CompositeError{
......@@ -125,6 +138,19 @@ func CompositeValidationError(errors ...error) *CompositeError {
}
}
// ValidateName recursively sets the name for all validations or updates them for nested properties
func (c *CompositeError) ValidateName(name string) *CompositeError {
for i, e := range c.Errors {
if ve, ok := e.(*Validation); ok {
c.Errors[i] = ve.ValidateName(name)
} else if ce, ok := e.(*CompositeError); ok {
c.Errors[i] = ce.ValidateName(name)
}
}
return c
}
// FailedAllPatternProperties an error for when the property doesn't match a pattern
func FailedAllPatternProperties(name, in, key string) *Validation {
msg := fmt.Sprintf(failedAllPatternProps, name, key, in)
......@@ -268,7 +294,7 @@ func DuplicateItems(name, in string) *Validation {
}
// TooManyItems error for when an array contains too many items
func TooManyItems(name, in string, max int64) *Validation {
func TooManyItems(name, in string, max int64, value interface{}) *Validation {
msg := fmt.Sprintf(maxItemsFail, name, in, max)
if in == "" {
msg = fmt.Sprintf(maxItemsFailNoIn, name, max)
......@@ -278,12 +304,13 @@ func TooManyItems(name, in string, max int64) *Validation {
code: MaxItemsFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
// TooFewItems error for when an array contains too few items
func TooFewItems(name, in string, min int64) *Validation {
func TooFewItems(name, in string, min int64, value interface{}) *Validation {
msg := fmt.Sprintf(minItemsFail, name, in, min)
if in == "" {
msg = fmt.Sprintf(minItemsFailNoIn, name, min)
......@@ -292,12 +319,13 @@ func TooFewItems(name, in string, min int64) *Validation {
code: MinItemsFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
// ExceedsMaximumInt error for when maxinum validation fails
func ExceedsMaximumInt(name, in string, max int64, exclusive bool) *Validation {
// ExceedsMaximumInt error for when maximum validation fails
func ExceedsMaximumInt(name, in string, max int64, exclusive bool, value interface{}) *Validation {
var message string
if in == "" {
m := maxIncFailNoIn
......@@ -316,13 +344,13 @@ func ExceedsMaximumInt(name, in string, max int64, exclusive bool) *Validation {
code: MaxFailCode,
Name: name,
In: in,
Value: max,
Value: value,
message: message,
}
}
// ExceedsMaximumUint error for when maxinum validation fails
func ExceedsMaximumUint(name, in string, max uint64, exclusive bool) *Validation {
// ExceedsMaximumUint error for when maximum validation fails
func ExceedsMaximumUint(name, in string, max uint64, exclusive bool, value interface{}) *Validation {
var message string
if in == "" {
m := maxIncFailNoIn
......@@ -341,13 +369,13 @@ func ExceedsMaximumUint(name, in string, max uint64, exclusive bool) *Validation
code: MaxFailCode,
Name: name,
In: in,
Value: max,
Value: value,
message: message,
}
}
// ExceedsMaximum error for when maxinum validation fails
func ExceedsMaximum(name, in string, max float64, exclusive bool) *Validation {
// ExceedsMaximum error for when maximum validation fails
func ExceedsMaximum(name, in string, max float64, exclusive bool, value interface{}) *Validation {
var message string
if in == "" {
m := maxIncFailNoIn
......@@ -366,13 +394,13 @@ func ExceedsMaximum(name, in string, max float64, exclusive bool) *Validation {
code: MaxFailCode,
Name: name,
In: in,
Value: max,
Value: value,
message: message,
}
}
// ExceedsMinimumInt error for when maxinum validation fails
func ExceedsMinimumInt(name, in string, min int64, exclusive bool) *Validation {
// ExceedsMinimumInt error for when minimum validation fails
func ExceedsMinimumInt(name, in string, min int64, exclusive bool, value interface{}) *Validation {
var message string
if in == "" {
m := minIncFailNoIn
......@@ -391,13 +419,13 @@ func ExceedsMinimumInt(name, in string, min int64, exclusive bool) *Validation {
code: MinFailCode,
Name: name,
In: in,
Value: min,
Value: value,
message: message,
}
}
// ExceedsMinimumUint error for when maxinum validation fails
func ExceedsMinimumUint(name, in string, min uint64, exclusive bool) *Validation {
// ExceedsMinimumUint error for when minimum validation fails
func ExceedsMinimumUint(name, in string, min uint64, exclusive bool, value interface{}) *Validation {
var message string
if in == "" {
m := minIncFailNoIn
......@@ -416,13 +444,13 @@ func ExceedsMinimumUint(name, in string, min uint64, exclusive bool) *Validation
code: MinFailCode,
Name: name,
In: in,
Value: min,
Value: value,
message: message,
}
}
// ExceedsMinimum error for when maxinum validation fails
func ExceedsMinimum(name, in string, min float64, exclusive bool) *Validation {
// ExceedsMinimum error for when minimum validation fails
func ExceedsMinimum(name, in string, min float64, exclusive bool, value interface{}) *Validation {
var message string
if in == "" {
m := minIncFailNoIn
......@@ -441,13 +469,13 @@ func ExceedsMinimum(name, in string, min float64, exclusive bool) *Validation {
code: MinFailCode,
Name: name,
In: in,
Value: min,
Value: value,
message: message,
}
}
// NotMultipleOf error for when multiple of validation fails
func NotMultipleOf(name, in string, multiple interface{}) *Validation {
func NotMultipleOf(name, in string, multiple, value interface{}) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(multipleOfFailNoIn, name, multiple)
......@@ -458,7 +486,7 @@ func NotMultipleOf(name, in string, multiple interface{}) *Validation {
code: MultipleOfFailCode,
Name: name,
In: in,
Value: multiple,
Value: value,
message: msg,
}
}
......@@ -483,7 +511,7 @@ func EnumFail(name, in string, value interface{}, values []interface{}) *Validat
}
// Required error for when a value is missing
func Required(name, in string) *Validation {
func Required(name, in string, value interface{}) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(requiredFailNoIn, name)
......@@ -494,12 +522,30 @@ func Required(name, in string) *Validation {
code: RequiredFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
// ReadOnly error for when a value is present in request
func ReadOnly(name, in string, value interface{}) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(readOnlyFailNoIn, name)
} else {
msg = fmt.Sprintf(readOnlyFail, name, in)
}
return &Validation{
code: ReadOnlyFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
// TooLong error for when a string is too long
func TooLong(name, in string, max int64) *Validation {
func TooLong(name, in string, max int64, value interface{}) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(tooLongMessageNoIn, name, max)
......@@ -510,12 +556,13 @@ func TooLong(name, in string, max int64) *Validation {
code: TooLongFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
// TooShort error for when a string is too short
func TooShort(name, in string, min int64) *Validation {
func TooShort(name, in string, min int64, value interface{}) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(tooShortMessageNoIn, name, min)
......@@ -527,13 +574,14 @@ func TooShort(name, in string, min int64) *Validation {
code: TooShortFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
// FailedPattern error for when a string fails a regex pattern match
// the pattern that is returned is the ECMA syntax version of the pattern not the golang version.
func FailedPattern(name, in, pattern string) *Validation {
func FailedPattern(name, in, pattern string, value interface{}) *Validation {
var msg string
if in == "" {
msg = fmt.Sprintf(patternFailNoIn, name, pattern)
......@@ -545,6 +593,7 @@ func FailedPattern(name, in, pattern string) *Validation {
code: PatternFailCode,
Name: name,
In: in,
Value: value,
message: msg,
}
}
......
......@@ -63,210 +63,263 @@ func TestSchemaErrors(t *testing.T) {
assert.EqualValues(t, UniqueFailCode, err.Code())
assert.Equal(t, "uniques shouldn't contain duplicates", err.Error())
err = TooManyItems("something", "query", 5)
err = TooManyItems("something", "query", 5, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxItemsFailCode, err.Code())
assert.Equal(t, "something in query should have at most 5 items", err.Error())
assert.Equal(t, 6, err.Value)
err = TooManyItems("something", "", 5)
err = TooManyItems("something", "", 5, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxItemsFailCode, err.Code())
assert.Equal(t, "something should have at most 5 items", err.Error())
assert.Equal(t, 6, err.Value)
err = TooFewItems("something", "", 5)
err = TooFewItems("something", "", 5, 4)
assert.Error(t, err)
assert.EqualValues(t, MinItemsFailCode, err.Code())
assert.Equal(t, "something should have at least 5 items", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMaximumInt("something", "query", 5, false)
err = ExceedsMaximumInt("something", "query", 5, false, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something in query should be less than or equal to 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumInt("something", "", 5, false)
err = ExceedsMaximumInt("something", "", 5, false, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something should be less than or equal to 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumInt("something", "query", 5, true)
err = ExceedsMaximumInt("something", "query", 5, true, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something in query should be less than 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumInt("something", "", 5, true)
err = ExceedsMaximumInt("something", "", 5, true, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something should be less than 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumUint("something", "query", 5, false)
err = ExceedsMaximumUint("something", "query", 5, false, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something in query should be less than or equal to 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumUint("something", "", 5, false)
err = ExceedsMaximumUint("something", "", 5, false, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something should be less than or equal to 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumUint("something", "query", 5, true)
err = ExceedsMaximumUint("something", "query", 5, true, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something in query should be less than 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximumUint("something", "", 5, true)
err = ExceedsMaximumUint("something", "", 5, true, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something should be less than 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximum("something", "query", 5, false)
err = ExceedsMaximum("something", "query", 5, false, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something in query should be less than or equal to 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximum("something", "", 5, false)
err = ExceedsMaximum("something", "", 5, false, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something should be less than or equal to 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximum("something", "query", 5, true)
err = ExceedsMaximum("something", "query", 5, true, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something in query should be less than 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMaximum("something", "", 5, true)
err = ExceedsMaximum("something", "", 5, true, 6)
assert.Error(t, err)
assert.EqualValues(t, MaxFailCode, err.Code())
assert.Equal(t, "something should be less than 5", err.Error())
assert.Equal(t, 6, err.Value)
err = ExceedsMinimumInt("something", "query", 5, false)
err = ExceedsMinimumInt("something", "query", 5, false, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something in query should be greater than or equal to 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumInt("something", "", 5, false)
err = ExceedsMinimumInt("something", "", 5, false, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something should be greater than or equal to 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumInt("something", "query", 5, true)
err = ExceedsMinimumInt("something", "query", 5, true, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something in query should be greater than 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumInt("something", "", 5, true)
err = ExceedsMinimumInt("something", "", 5, true, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something should be greater than 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumUint("something", "query", 5, false)
err = ExceedsMinimumUint("something", "query", 5, false, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something in query should be greater than or equal to 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumUint("something", "", 5, false)
err = ExceedsMinimumUint("something", "", 5, false, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something should be greater than or equal to 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumUint("something", "query", 5, true)
err = ExceedsMinimumUint("something", "query", 5, true, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something in query should be greater than 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimumUint("something", "", 5, true)
err = ExceedsMinimumUint("something", "", 5, true, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something should be greater than 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimum("something", "query", 5, false)
err = ExceedsMinimum("something", "query", 5, false, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something in query should be greater than or equal to 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimum("something", "", 5, false)
err = ExceedsMinimum("something", "", 5, false, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something should be greater than or equal to 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimum("something", "query", 5, true)
err = ExceedsMinimum("something", "query", 5, true, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something in query should be greater than 5", err.Error())
assert.Equal(t, 4, err.Value)
err = ExceedsMinimum("something", "", 5, true)
err = ExceedsMinimum("something", "", 5, true, 4)
assert.Error(t, err)
assert.EqualValues(t, MinFailCode, err.Code())
assert.Equal(t, "something should be greater than 5", err.Error())
assert.Equal(t, 4, err.Value)
err = NotMultipleOf("something", "query", 5)
err = NotMultipleOf("something", "query", 5, 1)
assert.Error(t, err)
assert.EqualValues(t, MultipleOfFailCode, err.Code())
assert.Equal(t, "something in query should be a multiple of 5", err.Error())
assert.Equal(t, 1, err.Value)
err = NotMultipleOf("something", "query", float64(5))
err = NotMultipleOf("something", "query", float64(5), float64(1))
assert.Error(t, err)
assert.EqualValues(t, MultipleOfFailCode, err.Code())
assert.Equal(t, "something in query should be a multiple of 5", err.Error())
assert.Equal(t, float64(1), err.Value)
err = NotMultipleOf("something", "query", uint64(5))
err = NotMultipleOf("something", "query", uint64(5), uint64(1))
assert.Error(t, err)
assert.EqualValues(t, MultipleOfFailCode, err.Code())
assert.Equal(t, "something in query should be a multiple of 5", err.Error())
assert.Equal(t, uint64(1), err.Value)
err = NotMultipleOf("something", "", 5)
err = NotMultipleOf("something", "", 5, 1)
assert.Error(t, err)
assert.EqualValues(t, MultipleOfFailCode, err.Code())
assert.Equal(t, "something should be a multiple of 5", err.Error())
assert.Equal(t, 1, err.Value)
err = EnumFail("something", "query", "yada", []interface{}{"hello", "world"})
assert.Error(t, err)
assert.EqualValues(t, EnumFailCode, err.Code())
assert.Equal(t, "something in query should be one of [hello world]", err.Error())
assert.Equal(t, "yada", err.Value)
err = EnumFail("something", "", "yada", []interface{}{"hello", "world"})
assert.Error(t, err)
assert.EqualValues(t, EnumFailCode, err.Code())
assert.Equal(t, "something should be one of [hello world]", err.Error())
assert.Equal(t, "yada", err.Value)
err = Required("something", "query")
err = Required("something", "query", nil)
assert.Error(t, err)
assert.EqualValues(t, RequiredFailCode, err.Code())
assert.Equal(t, "something in query is required", err.Error())
assert.Equal(t, nil, err.Value)
err = Required("something", "")
err = Required("something", "", nil)
assert.Error(t, err)
assert.EqualValues(t, RequiredFailCode, err.Code())
assert.Equal(t, "something is required", err.Error())
assert.Equal(t, nil, err.Value)
err = TooLong("something", "query", 5)
err = ReadOnly("something", "query", nil)
assert.Error(t, err)
assert.EqualValues(t, ReadOnlyFailCode, err.Code())
assert.Equal(t, "something in query is readOnly", err.Error())
assert.Equal(t, nil, err.Value)
err = ReadOnly("something", "", nil)
assert.Error(t, err)
assert.EqualValues(t, ReadOnlyFailCode, err.Code())
assert.Equal(t, "something is readOnly", err.Error())
assert.Equal(t, nil, err.Value)
err = TooLong("something", "query", 5, "abcdef")
assert.Error(t, err)
assert.EqualValues(t, TooLongFailCode, err.Code())
assert.Equal(t, "something in query should be at most 5 chars long", err.Error())
assert.Equal(t, "abcdef", err.Value)
err = TooLong("something", "", 5)
err = TooLong("something", "", 5, "abcdef")
assert.Error(t, err)
assert.EqualValues(t, TooLongFailCode, err.Code())
assert.Equal(t, "something should be at most 5 chars long", err.Error())
assert.Equal(t, "abcdef", err.Value)
err = TooShort("something", "query", 5)
err = TooShort("something", "query", 5, "a")
assert.Error(t, err)
assert.EqualValues(t, TooShortFailCode, err.Code())
assert.Equal(t, "something in query should be at least 5 chars long", err.Error())
assert.Equal(t, "a", err.Value)
err = TooShort("something", "", 5)
err = TooShort("something", "", 5, "a")
assert.Error(t, err)
assert.EqualValues(t, TooShortFailCode, err.Code())
assert.Equal(t, "something should be at least 5 chars long", err.Error())
assert.Equal(t, "a", err.Value)
err = FailedPattern("something", "query", "\\d+")
err = FailedPattern("something", "query", "\\d+", "a")
assert.Error(t, err)
assert.EqualValues(t, PatternFailCode, err.Code())
assert.Equal(t, "something in query should match '\\d+'", err.Error())
assert.Equal(t, "a", err.Value)
err = FailedPattern("something", "", "\\d+")
err = FailedPattern("something", "", "\\d+", "a")
assert.Error(t, err)
assert.EqualValues(t, PatternFailCode, err.Code())
assert.Equal(t, "something should match '\\d+'", err.Error())
assert.Equal(t, "a", err.Value)
err = InvalidTypeName("something")
assert.Error(t, err)
......@@ -293,72 +346,74 @@ func TestSchemaErrors(t *testing.T) {
assert.EqualValues(t, CompositeErrorCode, err2.Code())
assert.Equal(t, "validation failure list", err2.Error())
err2 = CompositeValidationError(fmt.Errorf("First error"), fmt.Errorf("Second error"))
err2 = CompositeValidationError(fmt.Errorf("first error"), fmt.Errorf("second error"))
assert.Error(t, err2)
assert.EqualValues(t, CompositeErrorCode, err2.Code())
assert.Equal(t, "validation failure list:\nFirst error\nSecond error", err2.Error())
assert.Equal(t, "validation failure list:\nfirst error\nsecond error", err2.Error())
//func MultipleOfMustBePositive(name, in string, factor interface{}) *Validation {
// func MultipleOfMustBePositive(name, in string, factor interface{}) *Validation {
err = MultipleOfMustBePositive("path", "body", float64(-10))
assert.Error(t, err)
assert.EqualValues(t, MultipleOfMustBePositiveCode, err.Code())
assert.Equal(t, `factor MultipleOf declared for path must be positive: -10`, err.Error())
assert.Equal(t, float64(-10), err.Value)
err = MultipleOfMustBePositive("path", "body", int64(-10))
assert.Error(t, err)
assert.EqualValues(t, MultipleOfMustBePositiveCode, err.Code())
assert.Equal(t, `factor MultipleOf declared for path must be positive: -10`, err.Error())
assert.Equal(t, int64(-10), err.Value)
// func PropertyNotAllowed(name, in, key string) *Validation {
err = PropertyNotAllowed("path", "body", "key")
assert.Error(t, err)
assert.EqualValues(t, UnallowedPropertyCode, err.Code())
//unallowedProperty = "%s.%s in %s is a forbidden property"
// unallowedProperty = "%s.%s in %s is a forbidden property"
assert.Equal(t, "path.key in body is a forbidden property", err.Error())
err = PropertyNotAllowed("path", "", "key")
assert.Error(t, err)
assert.EqualValues(t, UnallowedPropertyCode, err.Code())
//unallowedPropertyNoIn = "%s.%s is a forbidden property"
// unallowedPropertyNoIn = "%s.%s is a forbidden property"
assert.Equal(t, "path.key is a forbidden property", err.Error())
//func TooManyProperties(name, in string, n int64) *Validation {
// func TooManyProperties(name, in string, n int64) *Validation {
err = TooManyProperties("path", "body", 10)
assert.Error(t, err)
assert.EqualValues(t, TooManyPropertiesCode, err.Code())
//tooManyProperties = "%s in %s should have at most %d properties"
// tooManyProperties = "%s in %s should have at most %d properties"
assert.Equal(t, "path in body should have at most 10 properties", err.Error())
err = TooManyProperties("path", "", 10)
assert.Error(t, err)
assert.EqualValues(t, TooManyPropertiesCode, err.Code())
//tooManyPropertiesNoIn = "%s should have at most %d properties"
// tooManyPropertiesNoIn = "%s should have at most %d properties"
assert.Equal(t, "path should have at most 10 properties", err.Error())
err = TooFewProperties("path", "body", 10)
// func TooFewProperties(name, in string, n int64) *Validation {
assert.Error(t, err)
assert.EqualValues(t, TooFewPropertiesCode, err.Code())
//tooFewProperties = "%s in %s should have at least %d properties"
// tooFewProperties = "%s in %s should have at least %d properties"
assert.Equal(t, "path in body should have at least 10 properties", err.Error())
err = TooFewProperties("path", "", 10)
// func TooFewProperties(name, in string, n int64) *Validation {
assert.Error(t, err)
assert.EqualValues(t, TooFewPropertiesCode, err.Code())
//tooFewPropertiesNoIn = "%s should have at least %d properties"
// tooFewPropertiesNoIn = "%s should have at least %d properties"
assert.Equal(t, "path should have at least 10 properties", err.Error())
//func FailedAllPatternProperties(name, in, key string) *Validation {
// func FailedAllPatternProperties(name, in, key string) *Validation {
err = FailedAllPatternProperties("path", "body", "key")
assert.Error(t, err)
assert.EqualValues(t, FailedAllPatternPropsCode, err.Code())
//failedAllPatternProps = "%s.%s in %s failed all pattern properties"
// failedAllPatternProps = "%s.%s in %s failed all pattern properties"
assert.Equal(t, "path.key in body failed all pattern properties", err.Error())
err = FailedAllPatternProperties("path", "", "key")
assert.Error(t, err)
assert.EqualValues(t, FailedAllPatternPropsCode, err.Code())
//failedAllPatternPropsNoIn = "%s.%s failed all pattern properties"
// failedAllPatternPropsNoIn = "%s.%s failed all pattern properties"
assert.Equal(t, "path.key failed all pattern properties", err.Error())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment