diff --git a/bindings/errors.go b/bindings/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..14b8ad7785a38a29a5a2323287a9fa85680e8402 --- /dev/null +++ b/bindings/errors.go @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "context" + "strings" +) + +// ErrToUserErr maps backend patterns to user friendly error messages. +// Example format: +// (Back-end) "Building new HostPool because no HostList stored:": (Front-end) "Missing host list", +var ErrToUserErr = map[string]string{ + // todo populate with common errors +} + +// Error codes +const UnrecognizedCode = "UR: " +const UnrecognizedMessage = UnrecognizedCode + "Unrecognized error from XX backend, please report" + +// ErrorStringToUserFriendlyMessage takes a passed in errStr which will be +// a backend generated error. These may be error specifically written by +// the backend team or lower level errors gotten from low level dependencies. +// This function will parse the error string for common errors provided from +// ErrToUserErr to provide a more user-friendly error message for the front end. +// If the error is not common, some simple parsing is done on the error message +// to make it more user-accessible, removing backend specific jargon. +func ErrorStringToUserFriendlyMessage(errStr string) string { + // Go through common errors + for backendErr, userFriendly := range ErrToUserErr { + // Determine if error contains a common error + // Fixme: later versions may be improved by using regex + if strings.HasPrefix(errStr, backendErr) { + return userFriendly + } + } + + descStr := "desc = " + // If this contains an rpc error, determine how to handle it + if strings.Contains(errStr, context.DeadlineExceeded.Error()) { + // If there is a context deadline exceeded message, return the higher level + // as context deadline exceeded is not informative + rpcErr := "rpc " + rpcIdx := strings.Index(errStr, rpcErr) + return UnrecognizedCode + errStr[:rpcIdx] + } else if strings.Contains(errStr, descStr) { + // If containing an rpc error where context deadline exceeded + // is NOT involved, the error returned server-side is often + //more informative + descIdx := strings.Index(errStr, descStr) + // return everything after "desc = " + return UnrecognizedCode + errStr[descIdx+len(descStr):] + } + + // If a compound error message, return the highest level message + errParts := strings.Split(errStr, ":") + if len(errParts) > 1 { + // Return everything before the first : + return UnrecognizedCode + errParts[0] + } + + return UnrecognizedMessage +} diff --git a/bindings/errors_test.go b/bindings/errors_test.go new file mode 100644 index 0000000000000000000000000000000000000000..78115099fe32d1a8b40155350d306769fbe8fa51 --- /dev/null +++ b/bindings/errors_test.go @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright © 2020 xx network SEZC // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file // +/////////////////////////////////////////////////////////////////////////////// + +package bindings + +import ( + "context" + "strings" + "testing" +) + +// Unit test +func TestErrorStringToUserFriendlyMessage(t *testing.T) { + // Setup: Populate map + backendErrs := []string{"Failed to Unmarshal Conversation", "failed to create group key preimage", + "Failed to unmarshal SentRequestMap"} + userErrs := []string{"Could not retrieve conversation", "Failed to initiate group chat", + "Failed to pull up friend requests"} + + for i, exampleErr := range backendErrs { + ErrToUserErr[exampleErr] = userErrs[i] + } + + // Check if a mapped common error returns the expected user friendly error + received := ErrorStringToUserFriendlyMessage(backendErrs[0]) + if strings.Compare(received, userErrs[0]) != 0 { + t.Errorf("Unexpected user friendly message returned from common error mapping."+ + "\n\tExpected: %s"+ + "\n\tReceived: %v", userErrs[0], received) + } + + // Test RPC error in which high level information should + // be passed along (ie context deadline exceeded error) + expected := "Could not poll network: " + rpcPrefix := "rpc error: desc = " + rpcErr := expected + rpcPrefix + context.DeadlineExceeded.Error() + received = ErrorStringToUserFriendlyMessage(rpcErr) + if strings.Compare(UnrecognizedCode+expected, received) != 0 { + t.Errorf("Rpc error parsed unxecpectedly with error "+ + "\n\"%s\" "+ + "\n\tExpected: %s"+ + "\n\tReceived: %v", rpcErr, UnrecognizedCode+expected, received) + } + + // Test RPC error where server side error information is provided + serverSideError := "Could not parse message! Please try again with a properly crafted message" + rpcErr = rpcPrefix + serverSideError + received = ErrorStringToUserFriendlyMessage(rpcErr) + if strings.Compare(UnrecognizedCode+serverSideError, received) != 0 { + t.Errorf("RPC error parsed unexpectedly with error "+ + "\n\"%s\" "+ + "\n\tExpected: %s"+ + "\n\tReceived: %v", rpcErr, UnrecognizedCode+serverSideError, received) + } + + // Test uncommon error, should return highest level message + expected = "failed to register with permissioning" + uncommonErr := expected + ": sendRegistrationMessage: Unable to contact Identity Server" + received = ErrorStringToUserFriendlyMessage(uncommonErr) + if strings.Compare(received, UnrecognizedCode+expected) != 0 { + t.Errorf("Uncommon error parsed unexpectedly with error "+ + "\n\"%s\" "+ + "\n\tExpected: %s"+ + "\n\tReceived: %s", uncommonErr, UnrecognizedCode+expected, received) + } + + // Test fully unrecognizable and un-parsable message, + // should hardcoded error message + uncommonErr = "failed to register with permissioning" + received = ErrorStringToUserFriendlyMessage(uncommonErr) + if strings.Compare(UnrecognizedMessage, received) != 0 { + t.Errorf("Uncommon error parsed unexpectedly with error "+ + "\n\"%s\" "+ + "\n\tExpected: %s"+ + "\n\tReceived: %s", uncommonErr, UnrecognizedMessage, received) + } + +}