Skip to content

Commit

Permalink
Add MasterErrorPB handling
Browse files Browse the repository at this point in the history
  • Loading branch information
radekg committed Dec 12, 2021
1 parent e33326f commit 1a8b01c
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 5 deletions.
62 changes: 62 additions & 0 deletions errors/errors.go
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,
}
}
96 changes: 96 additions & 0 deletions errors/errors_test.go
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())
})

}
22 changes: 17 additions & 5 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,6 @@ func PString(a string) *string {
return &a
}

// PYQLDatabase returns a pointer to the given input YQLDatabase.
func PYQLDatabase(input ybApi.YQLDatabase) *ybApi.YQLDatabase {
return &input
}

// ReadInt reads an int from a reader.
func ReadInt(reader io.Reader) (int, error) {
intBuf := make([]byte, 4)
Expand Down Expand Up @@ -176,3 +171,20 @@ func computeUInt32SizeNoTag(value int) int {
}
return 5
}

// == YugabyteDB types

// PAppStatusErrorCode returns a pointer to the given input AppStatusErrorCode.
func PAppStatusErrorCode(input ybApi.AppStatusPB_ErrorCode) *ybApi.AppStatusPB_ErrorCode {
return &input
}

// PYQLDatabase returns a pointer to the given input YQLDatabase.
func PYQLDatabase(input ybApi.YQLDatabase) *ybApi.YQLDatabase {
return &input
}

// PMasterErrorCode returns a pointer to the given input MasterErrorCode.
func PMasterErrorCode(input ybApi.MasterErrorPB_Code) *ybApi.MasterErrorPB_Code {
return &input
}

0 comments on commit 1a8b01c

Please sign in to comment.