check for undefined brace captures + make tests parallel

This commit is contained in:
Adrien Marquès 2020-03-16 10:56:26 +01:00
parent c32b038da2
commit e7f10723a6
Signed by: xdrm-brackets
GPG Key ID: D75243CA236D825E
4 changed files with 94 additions and 14 deletions

View File

@ -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

View File

@ -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")

View File

@ -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
}

View File

@ -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)
}