Skip to content

Commit

Permalink
Merge "[FAB-8261] Introduce Multi Errors type"
Browse files Browse the repository at this point in the history
  • Loading branch information
troyronda authored and Gerrit Code Review committed Feb 14, 2018
2 parents 786e8c5 + 39a4250 commit b447674
Show file tree
Hide file tree
Showing 29 changed files with 374 additions and 365 deletions.
4 changes: 2 additions & 2 deletions api/apifabclient/mocks/mockfabclient.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 2 additions & 10 deletions api/apifabclient/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// ProposalProcessor simulates transaction proposal, so that a client can submit the result for ordering.
type ProposalProcessor interface {
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResult, error)
ProcessTransactionProposal(proposal TransactionProposal) (TransactionProposalResponse, error)
}

// ProposalSender provides the ability for a transaction proposal to be created and sent.
Expand Down Expand Up @@ -43,19 +43,11 @@ type TransactionProposal struct {
Proposal *pb.Proposal
}

// TransactionProposalResponse encapsulates both the result of transaction proposal processing and errors.
// TransactionProposalResponse respresents the result of transaction proposal processing.
type TransactionProposalResponse struct {
TransactionProposalResult
Err error // TODO: consider refactoring
}

// TransactionProposalResult respresents the result of transaction proposal processing.
type TransactionProposalResult struct {
Endorser string
Status int32

Proposal TransactionProposal
ProposalResponse *pb.ProposalResponse
}

// TODO: TransactionProposalResponse and TransactionProposalResult may need better names.
1 change: 0 additions & 1 deletion api/apitxn/resmgmtclient/resmgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ type InstallCCResponse struct {
Target string
Status int32
Info string
Err error
}

// InstantiateCCRequest contains instantiate chaincode request parameters
Expand Down
72 changes: 72 additions & 0 deletions pkg/errors/multi/multi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package multi

import (
"fmt"
"strings"
)

// Errors is used to represent multiple errors
type Errors []error

// New Errors object with the given errors. Only non-nil errors are added.
func New(errs ...error) error {
errors := Errors{}
for _, err := range errs {
if err != nil {
errors = append(errors, err)
}
}

if len(errors) == 0 {
return nil
}

if len(errors) == 1 {
return errors[0]
}

return errors
}

// Append error to Errors. If the first arg is not an Errors object, one will be created
func Append(errs error, err error) error {
m, ok := errs.(Errors)
if !ok {
return New(errs, err)
}
return append(m, err)
}

// ToError converts Errors to the error interface
// returns nil if no errors are present, a single error object if only one is present
func (errs Errors) ToError() error {
if len(errs) == 0 {
return nil
}
if len(errs) == 1 {
return errs[0]
}
return errs
}

// Error implements the error interface to return a string representation of Errors
func (errs Errors) Error() string {
if len(errs) == 0 {
return ""
}
if len(errs) == 1 {
return errs[0].Error()
}

errors := []string{fmt.Sprint("Multiple errors occurred: ")}
for _, err := range errs {
errors = append(errors, err.Error())
}
return strings.Join(errors, "\n")
}
63 changes: 63 additions & 0 deletions pkg/errors/multi/multi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package multi

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
)

func TestErrorString(t *testing.T) {
testErr := fmt.Errorf("test")
var errs Errors

assert.Equal(t, "", errs.Error())

errs = append(errs, testErr)
assert.Equal(t, testErr.Error(), errs.Error())

errs = append(errs, testErr)
assert.Equal(t, "Multiple errors occurred: \ntest\ntest", errs.Error())
}

func TestAppend(t *testing.T) {
testErr := fmt.Errorf("test")
testErr2 := fmt.Errorf("test2")

m := Append(nil, nil)
assert.Nil(t, m)

m = Append(nil, testErr)
assert.Equal(t, testErr, m)

m = Append(testErr, testErr2)
m1, ok := m.(Errors)
assert.True(t, ok)
assert.Equal(t, testErr, m1[0])
assert.Equal(t, testErr2, m1[1])

m = Append(Errors{testErr}, testErr2)
m1, ok = m.(Errors)
assert.True(t, ok)
assert.Equal(t, testErr, m1[0])
assert.Equal(t, testErr2, m1[1])
}

func TestToError(t *testing.T) {
testErr := fmt.Errorf("test")
var errs Errors

assert.Equal(t, nil, errs.ToError())

errs = append(errs, testErr)
assert.Equal(t, testErr, errs.ToError())

errs = append(errs, testErr)
assert.Equal(t, errs, errs.ToError())
}
4 changes: 4 additions & 0 deletions pkg/errors/status/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const (

// NoPeersFound No peers were discovered/configured
NoPeersFound Code = 6

// MultipleErrors multiple errors occurred
MultipleErrors Code = 7
)

// CodeName maps the codes in this packages to human-readable strings
Expand All @@ -49,6 +52,7 @@ var CodeName = map[int32]string{
4: "EMPTY_CERT",
5: "TIMEOUT",
6: "NO_PEERS_FOUND",
7: "MULTIPLE_ERRORS",
}

// ToInt32 cast to int32
Expand Down
8 changes: 6 additions & 2 deletions pkg/errors/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/pkg/errors"

"github.com/hyperledger/fabric-sdk-go/pkg/errors/multi"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
grpcstatus "google.golang.org/grpc/status"
)
Expand Down Expand Up @@ -94,8 +95,8 @@ func (g Group) String() string {
return UnknownStatus.String()
}

// FromError returns a Status representing err if it was produced from this
// package, otherwise it returns nil, false.
// FromError returns a Status representing err if available,
// otherwise it returns nil, false.
func FromError(err error) (s *Status, ok bool) {
if err == nil {
return &Status{Code: int32(OK)}, true
Expand All @@ -107,6 +108,9 @@ func FromError(err error) (s *Status, ok bool) {
if s, ok := unwrappedErr.(*Status); ok {
return s, true
}
if m, ok := unwrappedErr.(multi.Errors); ok {
return New(ClientStatus, MultipleErrors.ToInt32(), m.Error(), nil), true
}

return nil, false
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/errors/status/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"testing"

"github.com/hyperledger/fabric-sdk-go/pkg/errors/multi"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
"github.com/pkg/errors"
Expand Down Expand Up @@ -65,6 +66,14 @@ func TestFromError(t *testing.T) {

s, ok = FromError(fmt.Errorf("Test"))
assert.False(t, ok)

errs := multi.Errors{}
errs = append(errs, fmt.Errorf("Test"))
s, ok = FromError(errs)
assert.True(t, ok)
assert.Equal(t, ClientStatus, s.Group)
assert.EqualValues(t, MultipleErrors.ToInt32(), s.Code)
assert.Equal(t, errs.Error(), s.Message)
}

func TestStatusToError(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/fabric-client/channel/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ func (c *Channel) QueryByChaincode(request fab.ChaincodeInvokeRequest) ([][]byte
return nil, err
}
resps, err := queryChaincode(c.clientContext, c.name, request, targets)
return filterProposalResponses(resps, err)
return collectProposalResponses(resps), err
}

// QueryBySystemChaincode invokes a chaincode that isn't part of a channel.
Expand All @@ -443,5 +443,5 @@ func (c *Channel) QueryBySystemChaincode(request fab.ChaincodeInvokeRequest) ([]
return nil, err
}
resps, err := queryChaincode(c.clientContext, systemChannel, request, targets)
return filterProposalResponses(resps, err)
return collectProposalResponses(resps), err
}
Loading

0 comments on commit b447674

Please sign in to comment.