-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
175 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package errors | ||
|
||
import ( | ||
"fmt" | ||
|
||
ybApi "github.com/radekg/yugabyte-db-go-proto/v2/yb/api" | ||
) | ||
|
||
// MasterError is an error representation of the MasterErrorPB. | ||
type MasterError struct { | ||
Code *ybApi.MasterErrorPB_Code | ||
Status *ybApi.AppStatusPB | ||
} | ||
|
||
func (e *MasterError) statusToString() string { | ||
if e.Status == nil { | ||
return "status: <unknown>" | ||
} | ||
code := int32(999) | ||
status := ybApi.AppStatusPB_ErrorCode_name[code] | ||
if e.Status.Code != nil { | ||
if v, ok := ybApi.AppStatusPB_ErrorCode_name[int32(*e.Status.Code)]; ok { | ||
status = v | ||
code = int32(*e.Status.Code) | ||
} | ||
} | ||
errString := fmt.Sprintf("status: %d (%s)", code, status) | ||
if e.Status.Message != nil { | ||
errString = fmt.Sprintf("%s\n\tmessage: %s", errString, *e.Status.Message) | ||
} | ||
if e.Status.SourceFile != nil { | ||
errString = fmt.Sprintf("%s\n\tsource: %s", errString, *e.Status.SourceFile) | ||
if e.Status.SourceLine != nil { | ||
errString = fmt.Sprintf("%s@%d", errString, *e.Status.SourceLine) | ||
} | ||
} | ||
return errString | ||
} | ||
|
||
func (e *MasterError) Error() string { | ||
code := int32(1) | ||
codeName := ybApi.MasterErrorPB_Code_name[code] | ||
if e.Code != nil { | ||
if v, ok := ybApi.MasterErrorPB_Code_name[int32(*e.Code)]; ok { | ||
codeName = v | ||
code = int32(*e.Code) | ||
} | ||
} | ||
return fmt.Sprintf("rpc error: code: %d (%s), %s", | ||
code, codeName, e.statusToString()) | ||
} | ||
|
||
// ToError converts MasterErrorPB into an error. | ||
func ToError(genericError *ybApi.MasterErrorPB) error { | ||
if genericError == nil { | ||
return nil | ||
} | ||
return &MasterError{ | ||
Code: genericError.Code, | ||
Status: genericError.Status, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package errors | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/radekg/yugabyte-db-go-client/utils" | ||
ybApi "github.com/radekg/yugabyte-db-go-proto/v2/yb/api" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestErrors(t *testing.T) { | ||
|
||
t.Run("it=handles nil errors", func(tt *testing.T) { | ||
assert.Nil(tt, ToError(nil)) | ||
}) | ||
|
||
t.Run("it=handles errors with nil code", func(tt *testing.T) { | ||
anError := ToError(&ybApi.MasterErrorPB{}) | ||
typedError, ok := anError.(*MasterError) | ||
assert.True(tt, ok, "expected the error to be *MasterError") | ||
expectedErrorString := "rpc error: code: 1 (UNKNOWN_ERROR), status: <unknown>" | ||
assert.Equal(tt, expectedErrorString, typedError.Error()) | ||
}) | ||
|
||
t.Run("it=handles errors with nil status", func(tt *testing.T) { | ||
anError := ToError(&ybApi.MasterErrorPB{ | ||
Code: utils.PMasterErrorCode(ybApi.MasterErrorPB_INVALID_REQUEST), | ||
}) | ||
typedError, ok := anError.(*MasterError) | ||
assert.True(tt, ok, "expected the error to be *MasterError") | ||
expectedErrorString := "rpc error: code: 29 (INVALID_REQUEST), status: <unknown>" | ||
assert.Equal(tt, expectedErrorString, typedError.Error()) | ||
}) | ||
|
||
t.Run("it=handles errors with all details", func(tt *testing.T) { | ||
anError := ToError(&ybApi.MasterErrorPB{ | ||
Code: utils.PMasterErrorCode(ybApi.MasterErrorPB_INVALID_REQUEST), | ||
Status: &ybApi.AppStatusPB{ | ||
Code: utils.PAppStatusErrorCode(ybApi.AppStatusPB_ABORTED), | ||
Message: utils.PString("test error"), | ||
SourceFile: utils.PString("errors_test.go"), | ||
SourceLine: utils.PInt32(42), | ||
}, | ||
}) | ||
typedError, ok := anError.(*MasterError) | ||
assert.True(tt, ok, "expected the error to be *MasterError") | ||
expectedErrorString := "rpc error: code: 29 (INVALID_REQUEST), status: 11 (ABORTED)\n\tmessage: test error\n\tsource: errors_test.go@42" | ||
assert.Equal(tt, expectedErrorString, typedError.Error()) | ||
}) | ||
|
||
t.Run("it=handles errors without message", func(tt *testing.T) { | ||
anError := ToError(&ybApi.MasterErrorPB{ | ||
Code: utils.PMasterErrorCode(ybApi.MasterErrorPB_INVALID_REQUEST), | ||
Status: &ybApi.AppStatusPB{ | ||
Code: utils.PAppStatusErrorCode(ybApi.AppStatusPB_ABORTED), | ||
SourceFile: utils.PString("errors_test.go"), | ||
SourceLine: utils.PInt32(42), | ||
}, | ||
}) | ||
typedError, ok := anError.(*MasterError) | ||
assert.True(tt, ok, "expected the error to be *MasterError") | ||
expectedErrorString := "rpc error: code: 29 (INVALID_REQUEST), status: 11 (ABORTED)\n\tsource: errors_test.go@42" | ||
assert.Equal(tt, expectedErrorString, typedError.Error()) | ||
}) | ||
|
||
t.Run("it=handles errors without source line", func(tt *testing.T) { | ||
anError := ToError(&ybApi.MasterErrorPB{ | ||
Code: utils.PMasterErrorCode(ybApi.MasterErrorPB_INVALID_REQUEST), | ||
Status: &ybApi.AppStatusPB{ | ||
Code: utils.PAppStatusErrorCode(ybApi.AppStatusPB_ABORTED), | ||
Message: utils.PString("test error"), | ||
SourceFile: utils.PString("errors_test.go"), | ||
}, | ||
}) | ||
typedError, ok := anError.(*MasterError) | ||
assert.True(tt, ok, "expected the error to be *MasterError") | ||
expectedErrorString := "rpc error: code: 29 (INVALID_REQUEST), status: 11 (ABORTED)\n\tmessage: test error\n\tsource: errors_test.go" | ||
assert.Equal(tt, expectedErrorString, typedError.Error()) | ||
}) | ||
|
||
t.Run("it=handles errors without source information", func(tt *testing.T) { | ||
anError := ToError(&ybApi.MasterErrorPB{ | ||
Code: utils.PMasterErrorCode(ybApi.MasterErrorPB_INVALID_REQUEST), | ||
Status: &ybApi.AppStatusPB{ | ||
Code: utils.PAppStatusErrorCode(ybApi.AppStatusPB_ABORTED), | ||
Message: utils.PString("test error"), | ||
SourceLine: utils.PInt32(42), | ||
}, | ||
}) | ||
typedError, ok := anError.(*MasterError) | ||
assert.True(tt, ok, "expected the error to be *MasterError") | ||
expectedErrorString := "rpc error: code: 29 (INVALID_REQUEST), status: 11 (ABORTED)\n\tmessage: test error" | ||
assert.Equal(tt, expectedErrorString, typedError.Error()) | ||
}) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters