Skip to content

Commit

Permalink
Refactor method validation to its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
LLKennedy committed Nov 16, 2019
1 parent e50dba6 commit 73892ca
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 72 deletions.
12 changes: 6 additions & 6 deletions proxy/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,32 @@ import (
"reflect"
)

func argsMatch(expected, found reflect.Type) (bool, error) {
func validateArgs(expected, found reflect.Type) error {
expectedInLen := expected.NumIn()
expectedOutLen := expected.NumOut()
foundInLen := found.NumIn()
foundOutLen := found.NumOut()
if expectedInLen != foundInLen || expectedOutLen != foundOutLen {
return false, fmt.Errorf("api and server argument/return counts do not match")
return fmt.Errorf("api and server argument/return counts do not match")
}
if expectedInLen == 0 || !isStructPtr(expected.In(0)) || !isStructPtr(found.In(0)) {
return false, fmt.Errorf("no receiver")
return fmt.Errorf("no receiver")
}
for j := 1; j < expectedInLen; j++ {
expectedIn := expected.In(j)
foundIn := found.In(j)
if !typesMatch(expectedIn, foundIn) {
return false, fmt.Errorf("api and server arguments mismatch: %s vs %s", expectedIn.Kind(), foundIn.Kind())
return fmt.Errorf("api and server arguments mismatch: %s vs %s", expectedIn.Kind(), foundIn.Kind())
}
}
for j := 0; j < expectedOutLen; j++ {
expectedOut := expected.Out(j)
foundOut := found.Out(j)
if !typesMatch(expectedOut, foundOut) {
return false, fmt.Errorf("api and server returns mismatch: %s vs %s", expectedOut.Kind(), foundOut.Kind())
return fmt.Errorf("api and server returns mismatch: %s vs %s", expectedOut.Kind(), foundOut.Kind())
}
}
return true, nil
return nil
}

func typesMatch(expected, found reflect.Type) bool {
Expand Down
84 changes: 36 additions & 48 deletions proxy/args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,71 +47,60 @@ func Unrelated(a, b, c bool) string {

func TestArgsMatch(t *testing.T) {
type test struct {
name string
a, b interface{}
expectedBool bool
expectedErr string
name, expectedErr string
a, b interface{}
}
tests := []test{
{
name: "matching perfectly",
a: &thingA{},
b: &thingA{},
expectedBool: true,
name: "matching perfectly",
a: &thingA{},
b: &thingA{},
},
{
name: "matching, different definition",
a: &thingA{},
b: &thingC{},
expectedBool: true,
name: "matching, different definition",
a: &thingA{},
b: &thingC{},
},
{
name: "wrong argument",
a: &thingA{},
b: &thingB{},
expectedBool: false,
expectedErr: "api and server arguments mismatch: int vs string",
name: "wrong argument",
a: &thingA{},
b: &thingB{},
expectedErr: "api and server arguments mismatch: int vs string",
},
{
name: "no receiver on one",
a: &thingA{},
b: DoThing,
expectedBool: false,
expectedErr: "api and server argument/return counts do not match",
name: "no receiver on one",
a: &thingA{},
b: DoThing,
expectedErr: "api and server argument/return counts do not match",
},
{
name: "no receiver on both",
a: DoThing,
b: DoThing,
expectedBool: false,
expectedErr: "no receiver",
name: "no receiver on both",
a: DoThing,
b: DoThing,
expectedErr: "no receiver",
},
{
name: "total mismatch of same in-length",
a: &thingA{},
b: Unrelated,
expectedBool: false,
expectedErr: "no receiver",
name: "total mismatch of same in-length",
a: &thingA{},
b: Unrelated,
expectedErr: "no receiver",
},
{
name: "invalid pointer arguments",
a: &thingE{},
b: &thingA{},
expectedBool: false,
expectedErr: "api and server arguments mismatch: ptr vs int",
name: "invalid pointer arguments",
a: &thingE{},
b: &thingA{},
expectedErr: "api and server arguments mismatch: ptr vs int",
},
{
name: "valid pointer arguments",
a: &thingE{},
b: &thingE{},
expectedBool: true,
name: "valid pointer arguments",
a: &thingE{},
b: &thingE{},
},
{
name: "wrong return",
a: &thingA{},
b: &thingD{},
expectedBool: false,
expectedErr: "api and server returns mismatch: bool vs int",
name: "wrong return",
a: &thingA{},
b: &thingD{},
expectedErr: "api and server returns mismatch: bool vs int",
},
}
for _, tt := range tests {
Expand All @@ -129,8 +118,7 @@ func TestArgsMatch(t *testing.T) {
} else {
bType = reflect.TypeOf(tt.b)
}
match, err := argsMatch(aType, bType)
assert.Equal(t, tt.expectedBool, match)
err := validateArgs(aType, bType)
if tt.expectedErr == "" {
assert.NoError(t, err)
} else {
Expand Down
27 changes: 27 additions & 0 deletions proxy/methods.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package proxy

import (
"fmt"
"reflect"

"github.com/LLKennedy/httpgrpc/internal/methods"
)

func validateMethod(apiMethod reflect.Method, serverType reflect.Type) error {
name := apiMethod.Name
trueName, valid := methods.MatchAndStrip(name)
if !valid {
return fmt.Errorf("httpgrpc: %s does not begin with a valid HTTP method", name)
}
serverMethod, found := serverType.MethodByName(trueName)
if !found {
return fmt.Errorf("httpgrpc: server is missing method %s", trueName)
}
expectedType := apiMethod.Type
foundType := serverMethod.Type
err := validateArgs(expectedType, foundType)
if err != nil {
return fmt.Errorf("httpgrpc: api/server arguments do not match for method (%s/%s): %v", name, trueName, err)
}
return nil
}
21 changes: 3 additions & 18 deletions proxy/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"reflect"

"github.com/LLKennedy/httpgrpc"
"github.com/LLKennedy/httpgrpc/internal/methods"
"google.golang.org/grpc"
)

Expand Down Expand Up @@ -37,23 +36,9 @@ func (s *Server) setAPI(api, server interface{}) (err error) {
apiMethods := make([]string, apiType.NumMethod())
for i := range apiMethods {
apiMethod := apiType.Method(i)
name := apiMethod.Name
trueName, valid := methods.MatchAndStrip(name)
if !valid {
err = fmt.Errorf("httpgrpc: %s does not begin with a valid HTTP method", name)
break
}
serverMethod, found := serverType.MethodByName(trueName)
if !found {
err = fmt.Errorf("httpgrpc: server is missing method %s", trueName)
break
}
expectedType := apiMethod.Type
foundType := serverMethod.Type
matching, matchErr := argsMatch(expectedType, foundType)
if !matching {
err = fmt.Errorf("httpgrpc: api/server arguments do not match for method (%s/%s): %v", name, trueName, matchErr)
break
err := validateMethod(apiMethod, serverType)
if err != nil {
return err
}
}
if err == nil {
Expand Down

0 comments on commit 73892ca

Please sign in to comment.