Skip to content

Commit

Permalink
Add ability to pass arguments to error strings
Browse files Browse the repository at this point in the history
This commit adds the ability to pass in a variable number of arguments
to be used in formatting error messages that use the error handling
framework defined in core/errors.

Change-Id: I7747f2ee1ee5dbcaa3693b1e2e0c1205c159b02f
Signed-off-by: Will Lahti <wtlahti@us.ibm.com>
  • Loading branch information
wlahti committed Nov 2, 2016
1 parent 75cfb3b commit 89d2164
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 19 deletions.
34 changes: 21 additions & 13 deletions core/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ const (

// Result codes
const (
// Placeholder
// Placeholders
UnknownError ReasonCode = iota
ErrorWithArg ReasonCode = 1
)

// CallStackError is a general interface for
Expand All @@ -51,6 +52,8 @@ type CallStackError interface {
GetErrorCode() string
GetComponentCode() ComponentCode
GetReasonCode() ReasonCode
Message() string
MessageIn(string) string
}

type errormap map[string]map[string]map[string]string
Expand Down Expand Up @@ -81,6 +84,7 @@ type hlError struct {
stack callstack
componentcode ComponentCode
reasoncode ReasonCode
args []interface{}
stackGetter func(callstack) string
}

Expand Down Expand Up @@ -108,7 +112,7 @@ func setupHLError(e *hlError, debug bool) {

// Error comes from the error interface
func (h *hlError) Error() string {
return h.componentcode.Message(h.reasoncode)
return h.Message()
}

// GetStack returns the call stack as a string
Expand All @@ -131,33 +135,37 @@ func (h *hlError) GetErrorCode() string {
return fmt.Sprintf("%d-%d", h.componentcode, h.reasoncode)
}

// Message returns the corresponding error message for this code in default language
func (c ComponentCode) Message(reasoncode ReasonCode) string {
return emap[fmt.Sprintf("%d", c)][fmt.Sprintf("%d", reasoncode)][language]
// Message returns the corresponding error message for this error in default
// language.
// TODO - figure out the best way to read in system language instead of using
// hard-coded default language
func (h *hlError) Message() string {
return fmt.Sprintf(emap[fmt.Sprintf("%d", h.componentcode)][fmt.Sprintf("%d", h.reasoncode)][language], h.args...)
}

// MessageIn returns the corresponding error message for this code in 'language'
func (c ComponentCode) MessageIn(reasoncode ReasonCode, language string) string {
return emap[fmt.Sprintf("%d", c)][fmt.Sprintf("%d", reasoncode)][language]
// MessageIn returns the corresponding error message for this error in 'language'
func (h *hlError) MessageIn(language string) string {
return fmt.Sprintf(emap[fmt.Sprintf("%d", h.componentcode)][fmt.Sprintf("%d", h.reasoncode)][language], h.args...)
}

// Error creates a CallStackError using a specific Component Code and
// Reason Code (no callstack is recorded)
func Error(componentcode ComponentCode, reasoncode ReasonCode) CallStackError {
return newCustomError(componentcode, reasoncode, false)
func Error(componentcode ComponentCode, reasoncode ReasonCode, args ...interface{}) CallStackError {
return newCustomError(componentcode, reasoncode, false, args...)
}

// ErrorWithCallstack creates a CallStackError using a specific Component Code and
// Reason Code and fills its callstack
func ErrorWithCallstack(componentcode ComponentCode, reasoncode ReasonCode) CallStackError {
return newCustomError(componentcode, reasoncode, true)
func ErrorWithCallstack(componentcode ComponentCode, reasoncode ReasonCode, args ...interface{}) CallStackError {
return newCustomError(componentcode, reasoncode, true, args...)
}

func newCustomError(componentcode ComponentCode, reasoncode ReasonCode, generateStack bool) CallStackError {
func newCustomError(componentcode ComponentCode, reasoncode ReasonCode, generateStack bool, args ...interface{}) CallStackError {
e := &hlError{}
setupHLError(e, generateStack)
e.componentcode = componentcode
e.reasoncode = reasoncode
e.args = args
return e
}

Expand Down
4 changes: 3 additions & 1 deletion core/errors/errors_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package errors
const errorCodes string = `
{"0" :
{"0" :
{"en": "An unknown error occured."}
{"en": "An unknown error occurred."},
"1":
{"en": "An error occurred: %s"}
}
}`
51 changes: 46 additions & 5 deletions core/errors/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ func TestError(t *testing.T) {
}
}

// TestErrorWithArg tests creating an error with a message argument
func TestErrorWithArg(t *testing.T) {
e := Error(Utility, ErrorWithArg, "arg1")
s := e.GetStack()
if s != "" {
t.Fatalf("No error stack should have been recorded.")
}
}

func TestErrorWithCallstack(t *testing.T) {
e := ErrorWithCallstack(Utility, UnknownError)
s := e.GetStack()
Expand All @@ -37,6 +46,16 @@ func TestErrorWithCallstack(t *testing.T) {
}
}

// TestErrorWithCallstackAndArg tests creating an error with a callstack and
// message argument
func TestErrorWithCallstackAndArg(t *testing.T) {
e := ErrorWithCallstack(Utility, ErrorWithArg, "arg1")
s := e.GetStack()
if s == "" {
t.Fatalf("No error stack was recorded.")
}
}

func oops() CallStackError {
return Error(Utility, UnknownError)
}
Expand All @@ -48,14 +67,36 @@ func ExampleError() {
fmt.Printf("%s\n", err.GetErrorCode())
fmt.Printf("%d\n", err.GetComponentCode())
fmt.Printf("%d\n", err.GetReasonCode())
fmt.Printf("%s\n", err.GetComponentCode().Message(err.GetReasonCode()))
fmt.Printf("%s", err.GetComponentCode().MessageIn(err.GetReasonCode(), "en"))
fmt.Printf("%s\n", err.Message())
fmt.Printf("%s\n", err.MessageIn("en"))
// Output:
// An unknown error occured.
// An unknown error occurred.
// 0-0
// 0
// 0
// An unknown error occured.
// An unknown error occured.
// An unknown error occurred.
// An unknown error occurred.
}
}

// ExampleErrorWithArg tests the output for a sample error with a message
// argument
func ExampleErrorWithArg() {
err := Error(Utility, ErrorWithArg, "arg1")

if err != nil {
fmt.Printf("%s\n", err.Error())
fmt.Printf("%s\n", err.GetErrorCode())
fmt.Printf("%d\n", err.GetComponentCode())
fmt.Printf("%d\n", err.GetReasonCode())
fmt.Printf("%s\n", err.Message())
fmt.Printf("%s\n", err.MessageIn("en"))
// Output:
// An error occurred: arg1
// 0-1
// 0
// 1
// An error occurred: arg1
// An error occurred: arg1
}
}

0 comments on commit 89d2164

Please sign in to comment.