unexport dynfunc errors

This commit is contained in:
Adrien Marquès 2020-04-04 12:46:43 +02:00
parent df56496a16
commit 90472b8bf7
Signed by: xdrm-brackets
GPG Key ID: D75243CA236D825E
4 changed files with 57 additions and 58 deletions

View File

@ -3,49 +3,48 @@ package dynfunc
// cerr allows you to create constant "const" error with type boxing.
type cerr string
// Error implements the error builtin interface.
func (err cerr) Error() string {
return string(err)
}
// ErrHandlerNotFunc - handler is not a func
const ErrHandlerNotFunc = cerr("handler must be a func")
// errHandlerNotFunc - handler is not a func
const errHandlerNotFunc = cerr("handler must be a func")
// ErrNoServiceForHandler - no service matching this handler
const ErrNoServiceForHandler = cerr("no service found for this handler")
// errNoServiceForHandler - no service matching this handler
const errNoServiceForHandler = cerr("no service found for this handler")
// ErrMissingHandlerArgumentParam - missing params arguments for handler
const ErrMissingHandlerArgumentParam = cerr("missing handler argument : parameter struct")
// errMissingHandlerArgumentParam - missing params arguments for handler
const errMissingHandlerArgumentParam = cerr("missing handler argument : parameter struct")
// ErrUnexpectedInput - input argument is not expected
const ErrUnexpectedInput = cerr("unexpected input struct")
// errUnexpectedInput - input argument is not expected
const errUnexpectedInput = cerr("unexpected input struct")
// ErrMissingHandlerOutput - missing output for handler
const ErrMissingHandlerOutput = cerr("handler must have at least 1 output")
// errMissingHandlerOutput - missing output for handler
const errMissingHandlerOutput = cerr("handler must have at least 1 output")
// ErrMissingHandlerOutputError - missing error output for handler
const ErrMissingHandlerOutputError = cerr("handler must have its last output of type api.Error")
// errMissingHandlerOutputError - missing error output for handler
const errMissingHandlerOutputError = cerr("handler must have its last output of type api.Error")
// ErrMissingRequestArgument - missing request argument for handler
const ErrMissingRequestArgument = cerr("handler first argument must be of type api.Request")
// errMissingRequestArgument - missing request argument for handler
const errMissingRequestArgument = cerr("handler first argument must be of type api.Request")
// ErrMissingParamArgument - missing parameters argument for handler
const ErrMissingParamArgument = cerr("handler second argument must be a struct")
// errMissingParamArgument - missing parameters argument for handler
const errMissingParamArgument = cerr("handler second argument must be a struct")
// ErrUnexportedName - argument is unexported in struct
const ErrUnexportedName = cerr("unexported name")
// errUnexportedName - argument is unexported in struct
const errUnexportedName = cerr("unexported name")
// ErrMissingParamOutput - missing output argument for handler
const ErrMissingParamOutput = cerr("handler first output must be a *struct")
// errMissingParamOutput - missing output argument for handler
const errMissingParamOutput = cerr("handler first output must be a *struct")
// ErrMissingParamFromConfig - missing a parameter in handler struct
const ErrMissingParamFromConfig = cerr("missing a parameter from configuration")
// errMissingParamFromConfig - missing a parameter in handler struct
const errMissingParamFromConfig = cerr("missing a parameter from configuration")
// ErrMissingOutputFromConfig - missing a parameter in handler struct
const ErrMissingOutputFromConfig = cerr("missing a parameter from configuration")
// errMissingOutputFromConfig - missing a parameter in handler struct
const errMissingOutputFromConfig = cerr("missing a parameter from configuration")
// ErrWrongParamTypeFromConfig - a configuration parameter type is invalid in the handler param struct
const ErrWrongParamTypeFromConfig = cerr("invalid struct field type")
// errWrongParamTypeFromConfig - a configuration parameter type is invalid in the handler param struct
const errWrongParamTypeFromConfig = cerr("invalid struct field type")
// ErrMissingHandlerErrorOutput - missing handler output error
const ErrMissingHandlerErrorOutput = cerr("last output must be of type api.Error")
// errMissingHandlerErrorOutput - missing handler output error
const errMissingHandlerErrorOutput = cerr("last output must be of type api.Error")

View File

@ -32,7 +32,7 @@ func Build(fn interface{}, service config.Service) (*Handler, error) {
fnv := reflect.ValueOf(fn)
if fnv.Type().Kind() != reflect.Func {
return nil, ErrHandlerNotFunc
return nil, errHandlerNotFunc
}
if err := h.spec.checkInput(fnv); err != nil {

View File

@ -50,34 +50,34 @@ func (s spec) checkInput(fnv reflect.Value) error {
// no input -> ok
if len(s.Input) == 0 {
if fnt.NumIn() > 0 {
return ErrUnexpectedInput
return errUnexpectedInput
}
return nil
}
if fnt.NumIn() != 1 {
return ErrMissingHandlerArgumentParam
return errMissingHandlerArgumentParam
}
// arg must be a struct
structArg := fnt.In(0)
if structArg.Kind() != reflect.Struct {
return ErrMissingParamArgument
return errMissingParamArgument
}
// check for invalid param
for name, ptype := range s.Input {
if name[0] == strings.ToLower(name)[0] {
return fmt.Errorf("%s: %w", name, ErrUnexportedName)
return fmt.Errorf("%s: %w", name, errUnexportedName)
}
field, exists := structArg.FieldByName(name)
if !exists {
return fmt.Errorf("%s: %w", name, ErrMissingParamFromConfig)
return fmt.Errorf("%s: %w", name, errMissingParamFromConfig)
}
if !ptype.AssignableTo(field.Type) {
return fmt.Errorf("%s: %w (%s instead of %s)", name, ErrWrongParamTypeFromConfig, field.Type, ptype)
return fmt.Errorf("%s: %w (%s instead of %s)", name, errWrongParamTypeFromConfig, field.Type, ptype)
}
}
@ -88,13 +88,13 @@ func (s spec) checkInput(fnv reflect.Value) error {
func (s spec) checkOutput(fnv reflect.Value) error {
fnt := fnv.Type()
if fnt.NumOut() < 1 {
return ErrMissingHandlerOutput
return errMissingHandlerOutput
}
// last output must be api.Error
errOutput := fnt.Out(fnt.NumOut() - 1)
if !errOutput.AssignableTo(reflect.TypeOf(api.ErrorUnknown)) {
return ErrMissingHandlerErrorOutput
return errMissingHandlerErrorOutput
}
// no output -> ok
@ -103,29 +103,29 @@ func (s spec) checkOutput(fnv reflect.Value) error {
}
if fnt.NumOut() != 2 {
return ErrMissingParamOutput
return errMissingParamOutput
}
// fail if first output is not a pointer to struct
structOutputPtr := fnt.Out(0)
if structOutputPtr.Kind() != reflect.Ptr {
return ErrMissingParamOutput
return errMissingParamOutput
}
structOutput := structOutputPtr.Elem()
if structOutput.Kind() != reflect.Struct {
return ErrMissingParamOutput
return errMissingParamOutput
}
// fail on invalid output
for name, ptype := range s.Output {
if name[0] == strings.ToLower(name)[0] {
return fmt.Errorf("%s: %w", name, ErrUnexportedName)
return fmt.Errorf("%s: %w", name, errUnexportedName)
}
field, exists := structOutput.FieldByName(name)
if !exists {
return fmt.Errorf("%s: %w", name, ErrMissingOutputFromConfig)
return fmt.Errorf("%s: %w", name, errMissingOutputFromConfig)
}
// ignore types evalutating to nil
@ -134,7 +134,7 @@ func (s spec) checkOutput(fnv reflect.Value) error {
}
if !field.Type.ConvertibleTo(ptype) {
return fmt.Errorf("%s: %w (%s instead of %s)", name, ErrWrongParamTypeFromConfig, field.Type, ptype)
return fmt.Errorf("%s: %w (%s instead of %s)", name, errWrongParamTypeFromConfig, field.Type, ptype)
}
}

View File

@ -25,7 +25,7 @@ func TestInputCheck(t *testing.T) {
{
Input: map[string]reflect.Type{},
Fn: func(int, string) {},
Err: ErrUnexpectedInput,
Err: errUnexpectedInput,
},
// missing input struct in func
{
@ -33,7 +33,7 @@ func TestInputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func() {},
Err: ErrMissingHandlerArgumentParam,
Err: errMissingHandlerArgumentParam,
},
// input not a struct
{
@ -41,7 +41,7 @@ func TestInputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func(int) {},
Err: ErrMissingParamArgument,
Err: errMissingParamArgument,
},
// unexported param name
{
@ -49,7 +49,7 @@ func TestInputCheck(t *testing.T) {
"test1": reflect.TypeOf(int(0)),
},
Fn: func(struct{}) {},
Err: ErrUnexportedName,
Err: errUnexportedName,
},
// input field missing
{
@ -57,7 +57,7 @@ func TestInputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func(struct{}) {},
Err: ErrMissingParamFromConfig,
Err: errMissingParamFromConfig,
},
// input field invalid type
{
@ -65,7 +65,7 @@ func TestInputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func(struct{ Test1 string }) {},
Err: ErrWrongParamTypeFromConfig,
Err: errWrongParamTypeFromConfig,
},
// input field valid type
{
@ -115,13 +115,13 @@ func TestOutputCheck(t *testing.T) {
{
Output: map[string]reflect.Type{},
Fn: func() {},
Err: ErrMissingHandlerOutput,
Err: errMissingHandlerOutput,
},
// no input -> with last type not api.Error
{
Output: map[string]reflect.Type{},
Fn: func() bool { return true },
Err: ErrMissingHandlerErrorOutput,
Err: errMissingHandlerErrorOutput,
},
// no input -> with api.Error
{
@ -141,7 +141,7 @@ func TestOutputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func() api.Error { return api.ErrorSuccess },
Err: ErrMissingParamOutput,
Err: errMissingParamOutput,
},
// output not a pointer
{
@ -149,7 +149,7 @@ func TestOutputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func() (int, api.Error) { return 0, api.ErrorSuccess },
Err: ErrMissingParamOutput,
Err: errMissingParamOutput,
},
// output not a pointer to struct
{
@ -157,7 +157,7 @@ func TestOutputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func() (*int, api.Error) { return nil, api.ErrorSuccess },
Err: ErrMissingParamOutput,
Err: errMissingParamOutput,
},
// unexported param name
{
@ -165,7 +165,7 @@ func TestOutputCheck(t *testing.T) {
"test1": reflect.TypeOf(int(0)),
},
Fn: func() (*struct{}, api.Error) { return nil, api.ErrorSuccess },
Err: ErrUnexportedName,
Err: errUnexportedName,
},
// output field missing
{
@ -173,7 +173,7 @@ func TestOutputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func() (*struct{}, api.Error) { return nil, api.ErrorSuccess },
Err: ErrMissingParamFromConfig,
Err: errMissingParamFromConfig,
},
// output field invalid type
{
@ -181,7 +181,7 @@ func TestOutputCheck(t *testing.T) {
"Test1": reflect.TypeOf(int(0)),
},
Fn: func() (*struct{ Test1 string }, api.Error) { return nil, api.ErrorSuccess },
Err: ErrWrongParamTypeFromConfig,
Err: errWrongParamTypeFromConfig,
},
// output field valid type
{