test dynfunc package; standardize and refactor api #14
|
@ -2,8 +2,11 @@ package dynamic
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"git.xdrm.io/go/aicra/api"
|
||||
)
|
||||
|
||||
func TestInputCheck(t *testing.T) {
|
||||
|
@ -75,7 +78,7 @@ func TestInputCheck(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tcase := range tcases {
|
||||
t.Run("case."+string(i), func(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("case.%d", i), func(t *testing.T) {
|
||||
// mock spec
|
||||
s := spec{
|
||||
Input: tcase.Input,
|
||||
|
@ -101,3 +104,113 @@ func TestInputCheck(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutputCheck(t *testing.T) {
|
||||
tcases := []struct {
|
||||
Output map[string]reflect.Type
|
||||
Fn interface{}
|
||||
Err error
|
||||
}{
|
||||
// no input -> missing api.Error
|
||||
{
|
||||
Output: map[string]reflect.Type{},
|
||||
Fn: func() {},
|
||||
Err: ErrMissingHandlerOutput,
|
||||
},
|
||||
// no input -> with api.Error
|
||||
{
|
||||
Output: map[string]reflect.Type{},
|
||||
Fn: func() api.Error { return api.ErrorSuccess },
|
||||
Err: nil,
|
||||
},
|
||||
// func can have output if not specified
|
||||
{
|
||||
Output: map[string]reflect.Type{},
|
||||
Fn: func() (*struct{}, api.Error) { return nil, api.ErrorSuccess },
|
||||
Err: nil,
|
||||
},
|
||||
// missing output struct in func
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"Test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() api.Error { return api.ErrorSuccess },
|
||||
Err: ErrMissingParamOutput,
|
||||
},
|
||||
// output not a pointer
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"Test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() (int, api.Error) { return 0, api.ErrorSuccess },
|
||||
Err: ErrMissingParamOutput,
|
||||
},
|
||||
// output not a pointer to struct
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"Test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() (*int, api.Error) { return nil, api.ErrorSuccess },
|
||||
Err: ErrMissingParamOutput,
|
||||
},
|
||||
// unexported param name
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() (*struct{}, api.Error) { return nil, api.ErrorSuccess },
|
||||
Err: ErrUnexportedName,
|
||||
},
|
||||
// output field missing
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"Test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() (*struct{}, api.Error) { return nil, api.ErrorSuccess },
|
||||
Err: ErrMissingParamFromConfig,
|
||||
},
|
||||
// output field invalid type
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"Test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() (*struct{ Test1 string }, api.Error) { return nil, api.ErrorSuccess },
|
||||
Err: ErrWrongParamTypeFromConfig,
|
||||
},
|
||||
// output field valid type
|
||||
{
|
||||
Output: map[string]reflect.Type{
|
||||
"Test1": reflect.TypeOf(int(0)),
|
||||
},
|
||||
Fn: func() (*struct{ Test1 int }, api.Error) { return nil, api.ErrorSuccess },
|
||||
Err: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tcase := range tcases {
|
||||
t.Run(fmt.Sprintf("case.%d", i), func(t *testing.T) {
|
||||
// mock spec
|
||||
s := spec{
|
||||
Input: nil,
|
||||
Output: tcase.Output,
|
||||
}
|
||||
|
||||
err := s.checkOutput(reflect.ValueOf(tcase.Fn))
|
||||
if err == nil && tcase.Err != nil {
|
||||
t.Errorf("expected an error: '%s'", tcase.Err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
if err != nil && tcase.Err == nil {
|
||||
t.Errorf("unexpected error: '%s'", err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if err != nil && tcase.Err != nil {
|
||||
if !errors.Is(err, tcase.Err) {
|
||||
t.Errorf("expected the error <%s> got <%s>", tcase.Err, err)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue