Compare commits
No commits in common. "9c3166397fb95a18ef1bf1b208f691f62dc8abae" and "0e6dfbe580a32e388e33d81a05de23d9677e7c96" have entirely different histories.
9c3166397f
...
0e6dfbe580
|
@ -559,212 +559,6 @@ func TestParseParameters(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceCollision(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
tests := []struct {
|
|
||||||
Config string
|
|
||||||
Error error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/b",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
ErrPatternCollision,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/b",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/b",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/b",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "string" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
ErrPatternCollision,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/b",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "uint" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/b/d",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}/d",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "string" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
ErrPatternCollision,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "string" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
ErrPatternCollision,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123/d",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "string" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}/d",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "string" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "uint" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
ErrPatternCollision,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123/d",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "uint" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}/d",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "uint" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`[
|
|
||||||
{ "method": "GET", "path": "/a/123/d",
|
|
||||||
"info": "info", "in": {}
|
|
||||||
},
|
|
||||||
{ "method": "GET", "path": "/a/{c}/d",
|
|
||||||
"info": "info", "in": {
|
|
||||||
"{c}": { "info":"info", "type": "uint" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]`,
|
|
||||||
ErrPatternCollision,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("method.%d", i), func(t *testing.T) {
|
|
||||||
_, err := Parse(strings.NewReader(test.Config), builtin.StringDataType{}, builtin.UintDataType{})
|
|
||||||
|
|
||||||
if err == nil && test.Error != nil {
|
|
||||||
t.Errorf("expected an error: '%s'", test.Error.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if err != nil && test.Error == nil {
|
|
||||||
t.Errorf("unexpected error: '%s'", err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil && test.Error != nil {
|
|
||||||
if !errors.Is(err, test.Error) {
|
|
||||||
t.Errorf("expected the error <%s> got <%s>", test.Error, err)
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMatchSimple(t *testing.T) {
|
func TestMatchSimple(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
|
@ -74,8 +74,6 @@ func (server *Server) collide() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
partErrors := make([]error, 0)
|
|
||||||
|
|
||||||
// for each part
|
// for each part
|
||||||
for pi, aPart := range aParts {
|
for pi, aPart := range aParts {
|
||||||
bPart := bParts[pi]
|
bPart := bParts[pi]
|
||||||
|
@ -85,14 +83,13 @@ func (server *Server) collide() error {
|
||||||
|
|
||||||
// both captures -> as we cannot check, consider a collision
|
// both captures -> as we cannot check, consider a collision
|
||||||
if aIsCapture && bIsCapture {
|
if aIsCapture && bIsCapture {
|
||||||
partErrors = append(partErrors, fmt.Errorf("%s '%s': %w (path %s and %s)", aService.Method, aService.Pattern, ErrPatternCollision, aPart, bPart))
|
return fmt.Errorf("%s: %s '%s'", ErrPatternCollision, aService.Method, aService.Pattern)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no capture -> check equal
|
// no capture -> check equal
|
||||||
if !aIsCapture && !bIsCapture {
|
if !aIsCapture && !bIsCapture {
|
||||||
if aPart == bPart {
|
if aPart == bPart {
|
||||||
partErrors = append(partErrors, fmt.Errorf("%s '%s': %w (same path '%s')", aService.Method, aService.Pattern, ErrPatternCollision, aPart))
|
return fmt.Errorf("%s: %s '%s'", ErrPatternCollision, aService.Method, aService.Pattern)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -103,14 +100,12 @@ func (server *Server) collide() error {
|
||||||
|
|
||||||
// fail if no type or no validator
|
// fail if no type or no validator
|
||||||
if !exists || input.Validator == nil {
|
if !exists || input.Validator == nil {
|
||||||
partErrors = append(partErrors, fmt.Errorf("%s '%s': %w (invalid type for %s)", aService.Method, aService.Pattern, ErrPatternCollision, aPart))
|
return fmt.Errorf("%s: %s '%s'", ErrPatternCollision, aService.Method, aService.Pattern)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail if not valid
|
// fail if not valid
|
||||||
if _, valid := input.Validator(bPart); valid {
|
if _, valid := input.Validator(aPart); !valid {
|
||||||
partErrors = append(partErrors, fmt.Errorf("%s '%s': %w (%s captures '%s')", aService.Method, aService.Pattern, ErrPatternCollision, aPart, bPart))
|
return fmt.Errorf("%s: %s '%s'", ErrPatternCollision, aService.Method, aService.Pattern)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// B captures A -> check type (A is B ?)
|
// B captures A -> check type (A is B ?)
|
||||||
|
@ -119,37 +114,15 @@ func (server *Server) collide() error {
|
||||||
|
|
||||||
// fail if no type or no validator
|
// fail if no type or no validator
|
||||||
if !exists || input.Validator == nil {
|
if !exists || input.Validator == nil {
|
||||||
partErrors = append(partErrors, fmt.Errorf("%s '%s': %w (invalid type for %s)", bService.Method, bService.Pattern, ErrPatternCollision, bPart))
|
return fmt.Errorf("%s: %s '%s'", ErrPatternCollision, aService.Method, aService.Pattern)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail if not valid
|
// fail if not valid
|
||||||
if _, valid := input.Validator(aPart); valid {
|
if _, valid := input.Validator(bPart); !valid {
|
||||||
partErrors = append(partErrors, fmt.Errorf("%s '%s': %w (%s captures '%s')", bService.Method, bService.Pattern, ErrPatternCollision, bPart, aPart))
|
return fmt.Errorf("%s: %s '%s'", ErrPatternCollision, aService.Method, aService.Pattern)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partErrors = append(partErrors, nil)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// if at least 1 url part does not match -> ok
|
|
||||||
var firstError error
|
|
||||||
oneMismatch := false
|
|
||||||
for _, err := range partErrors {
|
|
||||||
if err != nil && firstError == nil {
|
|
||||||
firstError = err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
oneMismatch = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !oneMismatch {
|
|
||||||
return firstError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue