Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,6 @@ func TestComponents_Validate_Error(t *testing.T) {
c openapi.Components
err string
}{
{openapi.Components{
Schemas: openapi.Schemas{"Pet": &openapi.Schema{}},
}, `schemas["Pet"].type is required`},
{openapi.Components{
Schemas: openapi.Schemas{" ": &openapi.Schema{}},
}, `schemas[" "] (" ") is invalid: must match the regular expression "^[a-zA-Z0-9\\.\\-_]+$"`},
Expand Down
5 changes: 0 additions & 5 deletions content_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,6 @@ func TestContent_Validate_Error(t *testing.T) {
{openapi.Content{
"not a real media type": &openapi.MediaType{},
}, `["not a real media type"]: mime: expected slash after first token`},
{openapi.Content{
openapi.MediaRangeJSON: &openapi.MediaType{
Schema: &openapi.SchemaRef{Value: &openapi.Schema{}},
},
}, `["application/json"].schema.type is required`},
} {
t.Run(tc.err, func(t *testing.T) {
if err := tc.c.Validate(); err == nil || err.Error() != tc.err {
Expand Down
7 changes: 0 additions & 7 deletions document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,6 @@ func TestDocumentValidate_Error(t *testing.T) {
Schemas: openapi.Schemas{},
},
}, openapi.ErrEmptyDocument.Error()},
{&openapi.Document{
OpenAPI: "3.1.0",
Info: &openapi.Info{Title: "Sample API", Version: "1.0.0"},
Components: openapi.Components{
Schemas: openapi.Schemas{"Pet": &openapi.Schema{}},
},
}, `components.schemas["Pet"].type is required`},
{&openapi.Document{
OpenAPI: "3.1.0",
Info: &openapi.Info{Title: "Sample API", Version: "1.0.0"},
Expand Down
18 changes: 0 additions & 18 deletions header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,12 @@ func TestHeader_Validate_Error(t *testing.T) {
},
"schema and content are mutually exclusive",
},
{
openapi.Header{
Schema: &openapi.Schema{},
},
"schema.type is required",
},
{
openapi.Header{
Content: openapi.Content{},
},
"content is invalid: must contain exactly one entry, got 0",
},
{
openapi.Header{
Content: openapi.Content{
openapi.MediaRangeJSON: {
Schema: &openapi.SchemaRef{
Value: &openapi.Schema{},
},
},
},
},
`content["application/json"].schema.type is required`,
},
{openapi.Header{
Content: openapi.Content{openapi.MediaRangeJSON: {}},
Style: "foo",
Expand Down
6 changes: 0 additions & 6 deletions parameter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@ func TestParameter_Validate_Error(t *testing.T) {
In: openapi.ParameterLocationPath,
Required: true,
}, "schema or content is required"},
{openapi.Parameter{
Name: "myname",
In: openapi.ParameterLocationPath,
Required: true,
Schema: &openapi.Schema{},
}, "schema.type is required"},
{openapi.Parameter{
Name: "myname",
In: openapi.ParameterLocationPath,
Expand Down
6 changes: 0 additions & 6 deletions response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,6 @@ func TestResponse_Validate_Error(t *testing.T) {
Description: "some description",
Headers: openapi.Headers{"foo": {Value: &openapi.Header{}}},
}, `headers["foo"]: schema or content is required`},
{openapi.Response{
Description: "some description",
Content: openapi.Content{openapi.MediaRangeJSON: {
Schema: &openapi.SchemaRef{Value: &openapi.Schema{}},
}},
}, `content["application/json"].schema.type is required`},
{openapi.Response{
Description: "some description",
Links: openapi.Links{"address": {Value: &openapi.Link{}}},
Expand Down
54 changes: 27 additions & 27 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@ func setIndexSchema(s *Schema, idx int) *Schema { s.idx = idx; return s }
func (s *Schema) Validate() error {
s.Description = strings.TrimSpace(s.Description)

if s.Type == "" {
if len(s.AllOf) == 0 {
return &errpath.ErrField{Field: "type", Err: &errpath.ErrRequired{}}
// type is OPTIONAL — a schema without type accepts any value.
// See: https://spec.openapis.org/oas/v3.2.0.html#schema-object
if s.Type != "" {
if err := s.Type.Validate(); err != nil {
return &errpath.ErrField{Field: "type", Err: err}
}
} else if err := s.Type.Validate(); err != nil {
return &errpath.ErrField{Field: "type", Err: err}
}

if s.Format != "" {
Expand All @@ -113,14 +113,14 @@ func (s *Schema) Validate() error {
switch s.Format {
case "": // no format
case FormatInt32, FormatInt64, FormatUint, FormatUint32, FormatUint64:
if s.Type != TypeInteger {
if s.Type != "" && s.Type != TypeInteger {
return &errpath.ErrField{Field: "format", Err: &errpath.ErrInvalid[Format]{
Value: s.Format,
Message: fmt.Sprintf("only valid for integer type, got %s", s.Type),
}}
}
case FormatFloat, FormatDouble:
if s.Type != TypeNumber {
if s.Type != "" && s.Type != TypeNumber {
return &errpath.ErrField{Field: "format", Err: &errpath.ErrInvalid[Format]{
Value: s.Format,
Message: fmt.Sprintf("only valid for number type, got %s", s.Type),
Expand All @@ -129,25 +129,25 @@ func (s *Schema) Validate() error {
case FormatEmail, FormatPassword,
FormatUUID, FormatURI, FormatURIRef, FormatZipCode,
FormatIPv4, FormatIPv6:
if s.Type != TypeString {
if s.Type != "" && s.Type != TypeString {
return &errpath.ErrField{Field: "format", Err: &errpath.ErrInvalid[Format]{
Value: s.Format,
Message: fmt.Sprintf("only valid for string type, got %s", s.Type),
}}
}
case FormatDuration, FormatDate, FormatDateTime:
switch s.Type {
case TypeInteger, TypeString:
default:
return &errpath.ErrField{Field: "format", Err: &errpath.ErrInvalid[Format]{
Value: s.Format,
Message: fmt.Sprintf("only valid for integer or string type, got %s", s.Type),
}}
if s.Type != "" {
switch s.Type {
case TypeInteger, TypeString:
default:
return &errpath.ErrField{Field: "format", Err: &errpath.ErrInvalid[Format]{
Value: s.Format,
Message: fmt.Sprintf("only valid for integer or string type, got %s", s.Type),
}}
}
}
case FormatByte, FormatBinary:
switch s.Type {
case TypeString:
default:
if s.Type != "" && s.Type != TypeString {
return &errpath.ErrField{Field: "format", Err: &errpath.ErrInvalid[Format]{
Value: s.Format,
Message: fmt.Sprintf("only valid for string type, got %s", s.Type),
Expand Down Expand Up @@ -192,12 +192,12 @@ func (s *Schema) Validate() error {
Message: fmt.Sprintf("minimum is greater than maximum (%v > %v)", *s.Min, *s.Max),
}}
}
} else if s.Min != nil {
} else if s.Type != "" && s.Min != nil {
return &errpath.ErrField{Field: "minimum", Err: &errpath.ErrInvalid[float64]{
Value: *s.Min,
Message: fmt.Sprintf("only valid for number type, got %s", s.Type),
}}
} else if s.Max != nil {
} else if s.Type != "" && s.Max != nil {
return &errpath.ErrField{Field: "maximum", Err: &errpath.ErrInvalid[float64]{
Value: *s.Max,
Message: fmt.Sprintf("only valid for number type, got %s", s.Type),
Expand All @@ -206,7 +206,7 @@ func (s *Schema) Validate() error {

// String

if s.Type != TypeString && s.Enum != nil {
if s.Type != "" && s.Type != TypeString && s.Enum != nil {
return &errpath.ErrField{Field: "enum", Err: &errpath.ErrInvalid[string]{
Message: fmt.Sprintf("only valid for string type, got %s", s.Type),
}}
Expand All @@ -233,17 +233,17 @@ func (s *Schema) Validate() error {
return &errpath.ErrField{Field: "items", Err: err}
}
}
} else if s.MinItems != 0 {
} else if s.Type != "" && s.MinItems != 0 {
return &errpath.ErrField{Field: "minItems", Err: &errpath.ErrInvalid[uint]{
Value: s.MinItems,
Message: fmt.Sprintf("only valid for array type, got %s", s.Type),
}}
} else if s.MaxItems != nil {
} else if s.Type != "" && s.MaxItems != nil {
return &errpath.ErrField{Field: "maxItems", Err: &errpath.ErrInvalid[uint]{
Value: *s.MaxItems,
Message: fmt.Sprintf("only valid for array type, got %s", s.Type),
}}
} else if s.Items != nil {
} else if s.Type != "" && s.Items != nil {
return &errpath.ErrField{Field: "items", Err: &errpath.ErrInvalid[string]{
Message: fmt.Sprintf("only valid for array type, got %s", s.Type),
}}
Expand Down Expand Up @@ -275,11 +275,11 @@ func (s *Schema) Validate() error {
return &errpath.ErrField{Field: "additionalProperties", Err: err}
}
}
} else if s.Properties != nil {
} else if s.Type != "" && s.Properties != nil {
return &errpath.ErrField{Field: "properties", Err: &errpath.ErrInvalid[string]{
Message: fmt.Sprintf("only valid for object type, got %s", s.Type),
}}
} else if s.AdditionalProperties != nil {
} else if s.Type != "" && s.AdditionalProperties != nil {
return &errpath.ErrField{Field: "additionalProperties", Err: &errpath.ErrInvalid[string]{
Message: fmt.Sprintf("only valid for object type, got %s", s.Type),
}}
Expand All @@ -289,7 +289,7 @@ func (s *Schema) Validate() error {
switch dflt := s.Default.(type) {
case nil: // empty
case string:
if s.Type != TypeString {
if s.Type != "" && s.Type != TypeString {
return &errpath.ErrField{Field: "default", Err: &errpath.ErrInvalid[string]{
Value: dflt,
Message: fmt.Sprintf("does not match schema type, got %s", s.Type),
Expand Down
27 changes: 4 additions & 23 deletions schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func TestSchema_Validate(t *testing.T) {
{Type: openapi.TypeInteger, Default: 3.0},
{Type: openapi.TypeInteger, Format: openapi.FormatDuration, Default: 3}, // e.g. seconds
{Type: openapi.TypeString, Format: openapi.FormatByte}, // base64-encoded data
// type is OPTIONAL — a schema without type accepts any value
// See: https://spec.openapis.org/oas/v3.2.0.html#schema-object
{Description: "no type"},
{},
} {
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
if err := tc.Validate(); err != nil {
Expand All @@ -42,7 +46,6 @@ func TestSchema_Validate_Error(t *testing.T) {
s openapi.Schema
err string
}{
{openapi.Schema{}, "type is required"},
{openapi.Schema{
Type: "foo",
}, `type ("foo") is invalid, must be one of: "integer", "number", "string", "array", "boolean", "object", "null"`},
Expand Down Expand Up @@ -127,32 +130,10 @@ func TestSchema_Validate_Error(t *testing.T) {
MaxItems: pointer[uint](4),
Items: &openapi.SchemaRef{},
}, `minItems (5) is invalid: minItems is greater than maxItems (5 > 4)`},
{openapi.Schema{
AllOf: openapi.SchemaRefList{
{Value: &openapi.Schema{}},
},
}, `allOf[0].type is required`},
{openapi.Schema{
AllOf: openapi.SchemaRefList{
{Value: &openapi.Schema{}},
},
}, `allOf[0].type is required`},
{openapi.Schema{
Type: openapi.TypeObject,
Properties: openapi.SchemaRefs{
"foo": &openapi.SchemaRef{Value: &openapi.Schema{}},
},
}, `properties["foo"].type is required`},
{openapi.Schema{
Type: openapi.TypeObject,
Required: []string{"foo"},
}, `required[0] ("foo") is invalid: property does not exist`},
{openapi.Schema{
Type: openapi.TypeObject,
AdditionalProperties: &openapi.SchemaRef{
Value: &openapi.Schema{},
},
}, `additionalProperties.type is required`},
{openapi.Schema{
Type: openapi.TypeBoolean,
Properties: openapi.SchemaRefs{},
Expand Down
10 changes: 5 additions & 5 deletions vendor/github.com/MarkRosemaker/jsonutil/http_header.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions vendor/github.com/MarkRosemaker/jsonutil/url.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.