Skip to content

Commit

Permalink
[FAB-12340] response status >=200 && <400 success
Browse files Browse the repository at this point in the history
CC response codes between 200 and 400 were not treated appropriately.
Fix the success range in the tx utils and extend tests.

Change-Id: I819f06b4e0d3cc383185fb5ae623b8095ae90e4e
Signed-off-by: Matthew Sykes <sykesmat@us.ibm.com>
  • Loading branch information
sykesm committed Oct 10, 2018
1 parent e6d9c55 commit 3111724
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 16 deletions.
34 changes: 29 additions & 5 deletions integration/chaincode/simple/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,22 @@ func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02 Invoke")
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
switch function {
case "invoke":
// Make payment of X units from A to B
return t.invoke(stub, args)
} else if function == "delete" {
case "delete":
// Deletes an entity from its state
return t.delete(stub, args)
} else if function == "query" {
case "query":
// the old "Query" is now implemtned in invoke
return t.query(stub, args)
case "respond":
// return with an error
return t.respond(stub, args)
default:
return shim.Error(`Invalid invoke function name. Expecting "invoke", "delete", "query", or "respond"`)
}

return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}

// Transaction makes payment of X units from A to B
Expand Down Expand Up @@ -175,3 +179,23 @@ func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string)
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(Avalbytes)
}

// respond simply generates a response payload from the args
func (t *SimpleChaincode) respond(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 3 {
return shim.Error("expected three arguments")
}

status, err := strconv.ParseInt(args[0], 10, 32)
if err != nil {
return shim.Error(err.Error())
}
message := args[1]
payload := []byte(args[2])

return pb.Response{
Status: int32(status),
Message: message,
Payload: payload,
}
}
33 changes: 33 additions & 0 deletions integration/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ var _ = Describe("EndToEnd", func() {
peer := network.Peer("Org1", "peer1")

RunQueryInvokeQuery(network, orderer, peer)
RunRespondWith(network, orderer, peer)
})
})

Expand Down Expand Up @@ -145,3 +146,35 @@ func RunQueryInvokeQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer) {
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess).To(gbytes.Say("90"))
}

func RunRespondWith(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer) {
By("responding with a 300")
sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
ChannelID: "testchannel",
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
Name: "mycc",
Ctor: `{"Args":["respond","300","response-message","response-payload"]}`,
PeerAddresses: []string{
n.PeerAddress(n.Peer("Org2", "peer1"), nwo.ListenPort),
},
WaitForEvent: true,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(0))
Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:300"))

By("responding with a 400")
sess, err = n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
ChannelID: "testchannel",
Orderer: n.OrdererAddress(orderer, nwo.ListenPort),
Name: "mycc",
Ctor: `{"Args":["respond","400","response-message","response-payload"]}`,
PeerAddresses: []string{
n.PeerAddress(n.Peer("Org2", "peer1"), nwo.ListenPort),
},
WaitForEvent: true,
})
Expect(err).NotTo(HaveOccurred())
Eventually(sess, time.Minute).Should(gexec.Exit(1))
Expect(sess.Err).To(gbytes.Say(`Error: endorsement failure during invoke.`))
}
2 changes: 1 addition & 1 deletion protos/utils/txutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func CreateSignedTx(proposal *peer.Proposal, signer msp.SigningIdentity, resps .
for n, r := range resps {
if n == 0 {
a1 = r.Payload
if r.Response.Status != 200 {
if r.Response.Status < 200 || r.Response.Status >= 400 {
return nil, fmt.Errorf("Proposal response was not successful, error code %d, msg %s", r.Response.Status, r.Response.Message)
}
continue
Expand Down
72 changes: 62 additions & 10 deletions protos/utils/txutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package utils_test
import (
"encoding/hex"
"errors"
"strconv"
"testing"

"github.com/golang/protobuf/proto"
Expand Down Expand Up @@ -158,16 +159,6 @@ func TestCreateSignedTx(t *testing.T) {
})
prop.Header = headerBytes

// bad status
responses = []*pb.ProposalResponse{{
Payload: []byte("payload"),
Response: &pb.Response{
Status: int32(100),
},
}}
_, err = utils.CreateSignedTx(prop, signID, responses...)
assert.Error(t, err, "Expected error with status code not equal to 200")

// non-matching responses
responses = []*pb.ProposalResponse{{
Payload: []byte("payload"),
Expand Down Expand Up @@ -232,6 +223,67 @@ func TestCreateSignedTx(t *testing.T) {

}

func TestCreateSignedTxStatus(t *testing.T) {
serializedExtension, err := proto.Marshal(&pb.ChaincodeHeaderExtension{})
assert.NoError(t, err)
serializedChannelHeader, err := proto.Marshal(&cb.ChannelHeader{
Extension: serializedExtension,
})
assert.NoError(t, err)

signingID, err := mockmsp.NewNoopMsp().GetDefaultSigningIdentity()
assert.NoError(t, err)
serializedSigningID, err := signingID.Serialize()
assert.NoError(t, err)
serializedSignatureHeader, err := proto.Marshal(&cb.SignatureHeader{
Creator: serializedSigningID,
})
assert.NoError(t, err)

header := &cb.Header{
ChannelHeader: serializedChannelHeader,
SignatureHeader: serializedSignatureHeader,
}

serializedHeader, err := proto.Marshal(header)
assert.NoError(t, err)

proposal := &pb.Proposal{
Header: serializedHeader,
}

tests := []struct {
status int32
expectedErr string
}{
{status: 0, expectedErr: "Proposal response was not successful, error code 0, msg response-message"},
{status: 199, expectedErr: "Proposal response was not successful, error code 199, msg response-message"},
{status: 200, expectedErr: ""},
{status: 201, expectedErr: ""},
{status: 399, expectedErr: ""},
{status: 400, expectedErr: "Proposal response was not successful, error code 400, msg response-message"},
}
for _, tc := range tests {
t.Run(strconv.Itoa(int(tc.status)), func(t *testing.T) {
response := &pb.ProposalResponse{
Payload: []byte("payload"),
Endorsement: &pb.Endorsement{},
Response: &pb.Response{
Status: tc.status,
Message: "response-message",
},
}

_, err := utils.CreateSignedTx(proposal, signingID, response)
if tc.expectedErr == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, tc.expectedErr)
}
})
}
}

func TestCreateSignedEnvelope(t *testing.T) {
var env *cb.Envelope
channelID := "mychannelID"
Expand Down

0 comments on commit 3111724

Please sign in to comment.