diff --git a/bindings/client.go b/bindings/client.go index 09e0c7b6a6fc9ca4b643cf7cad645b7c466cd393..8e24a3b017ca18467f22f547a2b1a6cd2b4bda09 100644 --- a/bindings/client.go +++ b/bindings/client.go @@ -41,8 +41,8 @@ func init() { // BindingsClient wraps the api.Client, implementing additional functions // to support the gomobile Client interface type Client struct { - api api.Client - single *single.Manager + api api.Client + single *single.Manager singleMux sync.Mutex } @@ -504,8 +504,8 @@ func (b *BindingsClient) Search(data, separator string, func (c *Client) getSingle() (*single.Manager, error) { c.singleMux.Lock() defer c.singleMux.Unlock() - if c.single==nil{ - if !c.IsNetworkHealthy(){ + if c.single == nil { + if !c.IsNetworkHealthy() { return nil, errors.New("cannot return single manager, network si not healthy") } apiClient := &c.api @@ -514,4 +514,4 @@ func (c *Client) getSingle() (*single.Manager, error) { } return c.single, nil -} \ No newline at end of file +} diff --git a/bindings/errors.go b/bindings/errors.go index 09ffcb8170f4877182e9152c9db54bc896a8b1fe..cfffaf0155a8993787120d0bce24f6c1071baeb2 100644 --- a/bindings/errors.go +++ b/bindings/errors.go @@ -9,31 +9,36 @@ package bindings import ( "context" + "encoding/json" + "fmt" + "github.com/pkg/errors" "strings" + "sync" ) -// ErrToUserErr maps backend patterns to user friendly error messages. +// 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 +var errToUserErr = map[string]string{ // Registration errors - "cannot create username when network is not health" : - "Cannot create username, unable to connect to network", - "failed to add due to malformed fact stringified facts must at least have a type at the start" : - "Invalid fact, is the field empty?", - // UD failures - "failed to create user discovery manager: cannot return single manager, network is not health" : - "Could not connect to user discovery", - "user discovery returned error on search: no results found" : - "No results found", - "failed to search.: waiting for response to single-use transmisson timed out after 10s" : - "Search timed out", - "the phone number supplied was empty" : "Invalid phone number", - "failed to create user discovery manager: cannot start ud manager when network follower is not running." : - "Could not get network status", + //"cannot create username when network is not health" : + // "Cannot create username, unable to connect to network", + //"failed to add due to malformed fact stringified facts must at least have a type at the start" : + // "Invalid fact, is the field empty?", + //// UD failures + //"failed to create user discovery manager: cannot return single manager, network is not health" : + // "Could not connect to user discovery", + //"user discovery returned error on search: no results found" : + // "No results found", + //"failed to search.: waiting for response to single-use transmisson timed out after 10s" : + // "Search timed out", + //"the phone number supplied was empty" : "Invalid phone number", + //"failed to create user discovery manager: cannot start ud manager when network follower is not running." : + // "Could not get network status", } +var errorMux sync.RWMutex + // Error codes const UnrecognizedCode = "UR: " const UnrecognizedMessage = UnrecognizedCode + "Unrecognized error from XX backend, please report" @@ -42,12 +47,14 @@ const UnrecognizedMessage = UnrecognizedCode + "Unrecognized error from XX backe // 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. +// 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 { + errorMux.RLock() + defer errorMux.RUnlock() // Go through common errors - for backendErr, userFriendly := range ErrToUserErr { + for backendErr, userFriendly := range errToUserErr { // Determine if error contains a common error if strings.Contains(errStr, backendErr) { return userFriendly @@ -68,7 +75,7 @@ func ErrorStringToUserFriendlyMessage(errStr string) string { //more informative descIdx := strings.Index(errStr, descStr) // return everything after "desc = " - return errStr[descIdx+len(descStr):] + return errStr[descIdx+len(descStr):] } // If a compound error message, return the highest level message @@ -78,5 +85,21 @@ func ErrorStringToUserFriendlyMessage(errStr string) string { return UnrecognizedCode + errParts[0] } - return UnrecognizedMessage + return fmt.Sprintf("%s: %v", UnrecognizedCode, errStr) +} + +// UpdateCommonErrors takes the passed in contents of a JSON file and updates the +// errToUserErr map with the contents of the json file. The JSON's expected format +// conform with the commented examples provides in errToUserErr above. +// NOTE that you should not pass in a file path, but a preloaded JSON file +func UpdateCommonErrors(jsonFile string) error { + errorMux.Lock() + defer errorMux.Unlock() + err := json.Unmarshal([]byte(jsonFile), &errToUserErr) + if err != nil { + return errors.WithMessage(err, "Failed to unmarshal json file, "+ + "did you pass in the contents or the path?") + } + + return nil } diff --git a/bindings/errors_test.go b/bindings/errors_test.go index 0004d2a5ce7bd262f5ff698b58b372a7a6f4e7ec..d93a9924fb336e68fbe6c31af30174709f049d8d 100644 --- a/bindings/errors_test.go +++ b/bindings/errors_test.go @@ -22,7 +22,7 @@ func TestErrorStringToUserFriendlyMessage(t *testing.T) { "Failed to pull up friend requests"} for i, exampleErr := range backendErrs { - ErrToUserErr[exampleErr] = userErrs[i] + errToUserErr[exampleErr] = userErrs[i] } // Check if a mapped common error returns the expected user friendly error @@ -72,7 +72,7 @@ func TestErrorStringToUserFriendlyMessage(t *testing.T) { // should hardcoded error message uncommonErr = "failed to register with permissioning" received = ErrorStringToUserFriendlyMessage(uncommonErr) - if strings.Compare(UnrecognizedMessage, received) != 0 { + if strings.Compare(UnrecognizedCode+": "+uncommonErr, received) != 0 { t.Errorf("Uncommon error parsed unexpectedly with error "+ "\n\"%s\" "+ "\n\tExpected: %s"+ @@ -80,3 +80,28 @@ func TestErrorStringToUserFriendlyMessage(t *testing.T) { } } + +// Unit test +func TestClient_UpdateCommonErrors(t *testing.T) { + + key, expectedVal := "failed to create group key preimage", "Failed to initiate group chat" + + jsonData := "{\"Failed to Unmarshal Conversation\":\"Could not retrieve conversation\",\"Failed to unmarshal SentRequestMap\":\"Failed to pull up friend requests\",\"failed to create group key preimage\":\"Failed to initiate group chat\"}\n" + + err := UpdateCommonErrors(jsonData) + if err != nil { + t.Fatalf("UpdateCommonErrors error: %v", err) + } + + val, ok := errToUserErr[key] + if !ok { + t.Fatalf("Expected entry was not populated") + } + + if strings.Compare(expectedVal, val) != 0 { + t.Fatalf("Entry in updated error map was not expected."+ + "\n\tExpected: %s"+ + "\n\tReceived: %s", expectedVal, val) + } + +}