check for undefined brace captures + make tests parallel
This commit is contained in:
parent
c32b038da2
commit
e7f10723a6
|
@ -12,6 +12,8 @@ import (
|
|||
)
|
||||
|
||||
func TestLegalServiceName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
Raw string
|
||||
Error error
|
||||
|
@ -51,7 +53,7 @@ func TestLegalServiceName(t *testing.T) {
|
|||
},
|
||||
{
|
||||
`[ { "method": "GET", "info": "a", "path": "/invalid/{braces}" } ]`,
|
||||
nil,
|
||||
ErrUndefinedBraceCapture,
|
||||
},
|
||||
{
|
||||
`[ { "method": "GET", "info": "a", "path": "/invalid/s{braces}/abc" } ]`,
|
||||
|
@ -63,7 +65,7 @@ func TestLegalServiceName(t *testing.T) {
|
|||
},
|
||||
{
|
||||
`[ { "method": "GET", "info": "a", "path": "/invalid/{braces}/abc" } ]`,
|
||||
nil,
|
||||
ErrUndefinedBraceCapture,
|
||||
},
|
||||
{
|
||||
`[ { "method": "GET", "info": "a", "path": "/invalid/{b{races}s/abc" } ]`,
|
||||
|
@ -99,6 +101,7 @@ func TestLegalServiceName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
func TestAvailableMethods(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
Raw string
|
||||
ValidMethod bool
|
||||
|
@ -146,6 +149,7 @@ func TestAvailableMethods(t *testing.T) {
|
|||
}
|
||||
}
|
||||
func TestParseEmpty(t *testing.T) {
|
||||
t.Parallel()
|
||||
reader := strings.NewReader(`[]`)
|
||||
_, err := Parse(reader)
|
||||
if err != nil {
|
||||
|
@ -167,6 +171,7 @@ func TestParseJsonError(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParseMissingMethodDescription(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
Raw string
|
||||
ValidDescription bool
|
||||
|
@ -217,6 +222,7 @@ func TestParseMissingMethodDescription(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParamEmptyRenameNoRename(t *testing.T) {
|
||||
t.Parallel()
|
||||
reader := strings.NewReader(`[
|
||||
{
|
||||
"method": "GET",
|
||||
|
@ -247,6 +253,7 @@ func TestParamEmptyRenameNoRename(t *testing.T) {
|
|||
|
||||
}
|
||||
func TestOptionalParam(t *testing.T) {
|
||||
t.Parallel()
|
||||
reader := strings.NewReader(`[
|
||||
{
|
||||
"method": "GET",
|
||||
|
@ -288,6 +295,7 @@ func TestOptionalParam(t *testing.T) {
|
|||
|
||||
}
|
||||
func TestParseParameters(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
Raw string
|
||||
Error error
|
||||
|
@ -473,6 +481,57 @@ func TestParseParameters(t *testing.T) {
|
|||
]`,
|
||||
nil,
|
||||
},
|
||||
|
||||
{ // URI parameter
|
||||
`[
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{uri}",
|
||||
"info": "info",
|
||||
"in": {
|
||||
"{uri}": { "info": "valid", "type": "any", "name": "freename" }
|
||||
}
|
||||
}
|
||||
]`,
|
||||
nil,
|
||||
},
|
||||
{ // URI parameter cannot be optional
|
||||
`[
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{uri}",
|
||||
"info": "info",
|
||||
"in": {
|
||||
"{uri}": { "info": "valid", "type": "?any", "name": "freename" }
|
||||
}
|
||||
}
|
||||
]`,
|
||||
ErrIllegalOptionalURIParam,
|
||||
},
|
||||
{ // URI parameter not specified
|
||||
`[
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"info": "info",
|
||||
"in": {
|
||||
"{uri}": { "info": "valid", "type": "?any", "name": "freename" }
|
||||
}
|
||||
}
|
||||
]`,
|
||||
ErrUnspecifiedBraceCapture,
|
||||
},
|
||||
{ // URI parameter not defined
|
||||
`[
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/{uri}",
|
||||
"info": "info",
|
||||
"in": { }
|
||||
}
|
||||
]`,
|
||||
ErrUndefinedBraceCapture,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
|
@ -501,6 +560,7 @@ func TestParseParameters(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMatchSimple(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
Config string
|
||||
URL string
|
||||
|
|
|
@ -29,9 +29,15 @@ const ErrInvalidPatternBraceCapture = Error("invalid uri capturing braces")
|
|||
// ErrUnspecifiedBraceCapture - a parameter brace capture is not specified in the pattern
|
||||
const ErrUnspecifiedBraceCapture = Error("capturing brace missing in the path")
|
||||
|
||||
// ErrUndefinedBraceCapture - a parameter brace capture in the pattern is not defined in parameters
|
||||
const ErrUndefinedBraceCapture = Error("capturing brace missing input definition")
|
||||
|
||||
// ErrMissingDescription - a service is missing its description
|
||||
const ErrMissingDescription = Error("missing description")
|
||||
|
||||
// ErrIllegalOptionalURIParam - an URI parameter cannot be optional
|
||||
const ErrIllegalOptionalURIParam = Error("URI parameter cannot be optional")
|
||||
|
||||
// ErrMissingParamDesc - a parameter is missing its description
|
||||
const ErrMissingParamDesc = Error("missing parameter description")
|
||||
|
||||
|
|
|
@ -40,6 +40,17 @@ func Parse(r io.Reader, dtypes ...datatype.T) (*Server, error) {
|
|||
return server, nil
|
||||
}
|
||||
|
||||
// Find a service matching an incoming HTTP request
|
||||
func (server Server) Find(r *http.Request) *Service {
|
||||
for _, service := range server.Services {
|
||||
if matches := service.Match(r); matches {
|
||||
return service
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// collide returns if there is collision between services
|
||||
func (server *Server) collide() error {
|
||||
length := len(server.Services)
|
||||
|
@ -120,17 +131,6 @@ func (server *Server) collide() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Find a service matching an incoming HTTP request
|
||||
func (server Server) Find(r *http.Request) *Service {
|
||||
for _, service := range server.Services {
|
||||
if matches := service.Match(r); matches {
|
||||
return service
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkAndFormat checks for errors and missing fields and sets default values for optional fields.
|
||||
func (server Server) checkAndFormat() error {
|
||||
for _, service := range server.Services {
|
||||
|
@ -159,6 +159,13 @@ func (server Server) checkAndFormat() error {
|
|||
return fmt.Errorf("%s '%s' [in]: %w", service.Method, service.Pattern, err)
|
||||
}
|
||||
|
||||
// fail if a brace capture remains undefined
|
||||
for _, capture := range service.Captures {
|
||||
if capture.Ref == nil {
|
||||
return fmt.Errorf("%s '%s' [in]: %s: %w", service.Method, service.Pattern, capture.Name, ErrUndefinedBraceCapture)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -100,7 +100,8 @@ func (svc *Service) checkAndFormatInput(types []datatype.T) error {
|
|||
return fmt.Errorf("%s: %w", paramName, ErrIllegalParamName)
|
||||
}
|
||||
|
||||
// fail if brace does not exists in pattern
|
||||
// fail if brace capture does not exists in pattern
|
||||
iscapture := false
|
||||
if matches := braceRegex.FindAllStringSubmatch(paramName, -1); len(matches) > 0 && len(matches[0]) > 1 {
|
||||
braceName := matches[0][1]
|
||||
|
||||
|
@ -115,6 +116,7 @@ func (svc *Service) checkAndFormatInput(types []datatype.T) error {
|
|||
if !found {
|
||||
return fmt.Errorf("%s: %w", paramName, ErrUnspecifiedBraceCapture)
|
||||
}
|
||||
iscapture = true
|
||||
}
|
||||
|
||||
// use param name if no rename
|
||||
|
@ -127,6 +129,11 @@ func (svc *Service) checkAndFormatInput(types []datatype.T) error {
|
|||
return fmt.Errorf("%s: %w", paramName, err)
|
||||
}
|
||||
|
||||
// capture parameter cannot be optional
|
||||
if iscapture && param.Optional {
|
||||
return fmt.Errorf("%s: %w", paramName, ErrIllegalOptionalURIParam)
|
||||
}
|
||||
|
||||
if !param.assignDataType(types) {
|
||||
return fmt.Errorf("%s: %w", paramName, ErrUnknownDataType)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue