github.com/lzy4123/fabric@v2.1.1+incompatible/internal/peer/lifecycle/chaincode/checkcommitreadiness_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package chaincode_test 8 9 import ( 10 "encoding/json" 11 "fmt" 12 13 "github.com/golang/protobuf/proto" 14 pb "github.com/hyperledger/fabric-protos-go/peer" 15 lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle" 16 "github.com/hyperledger/fabric/bccsp/sw" 17 "github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode" 18 "github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode/mock" 19 "github.com/pkg/errors" 20 "github.com/spf13/cobra" 21 22 . "github.com/onsi/ginkgo" 23 . "github.com/onsi/gomega" 24 "github.com/onsi/gomega/gbytes" 25 ) 26 27 var _ = Describe("CheckCommitReadiness", func() { 28 Describe("CommitReadinessChecker", func() { 29 var ( 30 mockProposalResponse *pb.ProposalResponse 31 mockEndorserClient *mock.EndorserClient 32 mockSigner *mock.Signer 33 input *chaincode.CommitReadinessCheckInput 34 commitReadinessChecker *chaincode.CommitReadinessChecker 35 ) 36 37 BeforeEach(func() { 38 mockEndorserClient = &mock.EndorserClient{} 39 mockResult := &lb.CheckCommitReadinessResult{ 40 Approvals: map[string]bool{ 41 "seemsfinetome": true, 42 "well...ok": true, 43 "absolutely-not": false, 44 }, 45 } 46 mockResultBytes, err := proto.Marshal(mockResult) 47 Expect(err).NotTo(HaveOccurred()) 48 Expect(mockResultBytes).NotTo(BeNil()) 49 mockProposalResponse = &pb.ProposalResponse{ 50 Response: &pb.Response{ 51 Status: 200, 52 Payload: mockResultBytes, 53 }, 54 Endorsement: &pb.Endorsement{}, 55 } 56 mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil) 57 58 input = &chaincode.CommitReadinessCheckInput{ 59 ChannelID: "testchannel", 60 Name: "testcc", 61 Version: "1.0", 62 Sequence: 1, 63 } 64 65 mockSigner = &mock.Signer{} 66 buffer := gbytes.NewBuffer() 67 68 commitReadinessChecker = &chaincode.CommitReadinessChecker{ 69 Input: input, 70 EndorserClient: mockEndorserClient, 71 Signer: mockSigner, 72 Writer: buffer, 73 } 74 }) 75 76 It("checks whether a chaincode definition is ready to commit and writes the output as human readable plain-text", func() { 77 err := commitReadinessChecker.ReadinessCheck() 78 Expect(err).NotTo(HaveOccurred()) 79 Eventually(commitReadinessChecker.Writer).Should(gbytes.Say("Chaincode definition for chaincode 'testcc', version '1.0', sequence '1' on channel 'testchannel' approval status by org")) 80 Eventually(commitReadinessChecker.Writer).Should(gbytes.Say("absolutely-not: false")) 81 Eventually(commitReadinessChecker.Writer).Should(gbytes.Say("seemsfinetome: true")) 82 Eventually(commitReadinessChecker.Writer).Should(gbytes.Say("well...ok: true")) 83 }) 84 85 Context("when JSON-formatted output is requested", func() { 86 BeforeEach(func() { 87 commitReadinessChecker.Input.OutputFormat = "json" 88 }) 89 90 It("checks whether a chaincode definition is ready to commit and writes the output as JSON", func() { 91 err := commitReadinessChecker.ReadinessCheck() 92 Expect(err).NotTo(HaveOccurred()) 93 expectedOutput := &lb.CheckCommitReadinessResult{ 94 Approvals: map[string]bool{ 95 "absolutely-not": false, 96 "well...ok": true, 97 "seemsfinetome": true, 98 }, 99 } 100 json, err := json.MarshalIndent(expectedOutput, "", "\t") 101 Eventually(commitReadinessChecker.Writer).Should(gbytes.Say(fmt.Sprintf("%s", string(json)))) 102 }) 103 }) 104 105 Context("when the channel name is not provided", func() { 106 BeforeEach(func() { 107 commitReadinessChecker.Input.ChannelID = "" 108 }) 109 110 It("returns an error", func() { 111 err := commitReadinessChecker.ReadinessCheck() 112 Expect(err).To(MatchError("The required parameter 'channelID' is empty. Rerun the command with -C flag")) 113 }) 114 }) 115 116 Context("when the chaincode name is not provided", func() { 117 BeforeEach(func() { 118 commitReadinessChecker.Input.Name = "" 119 }) 120 121 It("returns an error", func() { 122 err := commitReadinessChecker.ReadinessCheck() 123 Expect(err).To(MatchError("The required parameter 'name' is empty. Rerun the command with -n flag")) 124 }) 125 }) 126 127 Context("when the chaincode version is not provided", func() { 128 BeforeEach(func() { 129 commitReadinessChecker.Input.Version = "" 130 }) 131 132 It("returns an error", func() { 133 err := commitReadinessChecker.ReadinessCheck() 134 Expect(err).To(MatchError("The required parameter 'version' is empty. Rerun the command with -v flag")) 135 }) 136 }) 137 138 Context("when the sequence is not provided", func() { 139 BeforeEach(func() { 140 commitReadinessChecker.Input.Sequence = 0 141 }) 142 143 It("returns an error", func() { 144 err := commitReadinessChecker.ReadinessCheck() 145 Expect(err).To(MatchError("The required parameter 'sequence' is empty. Rerun the command with --sequence flag")) 146 }) 147 }) 148 149 Context("when the signer cannot be serialized", func() { 150 BeforeEach(func() { 151 mockSigner.SerializeReturns(nil, errors.New("cafe")) 152 }) 153 154 It("returns an error", func() { 155 err := commitReadinessChecker.ReadinessCheck() 156 Expect(err).To(MatchError("failed to create proposal: failed to serialize identity: cafe")) 157 }) 158 }) 159 160 Context("when the signer fails to sign the proposal", func() { 161 BeforeEach(func() { 162 mockSigner.SignReturns(nil, errors.New("tea")) 163 }) 164 165 It("returns an error", func() { 166 err := commitReadinessChecker.ReadinessCheck() 167 Expect(err).To(MatchError("failed to create signed proposal: tea")) 168 }) 169 }) 170 171 Context("when the endorser fails to endorse the proposal", func() { 172 BeforeEach(func() { 173 mockEndorserClient.ProcessProposalReturns(nil, errors.New("latte")) 174 }) 175 176 It("returns an error", func() { 177 err := commitReadinessChecker.ReadinessCheck() 178 Expect(err).To(MatchError("failed to endorse proposal: latte")) 179 }) 180 }) 181 182 Context("when the endorser returns a nil proposal response", func() { 183 BeforeEach(func() { 184 mockProposalResponse = nil 185 mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil) 186 }) 187 188 It("returns an error", func() { 189 err := commitReadinessChecker.ReadinessCheck() 190 Expect(err).To(MatchError("received nil proposal response")) 191 }) 192 }) 193 194 Context("when the endorser returns a proposal response with a nil response", func() { 195 BeforeEach(func() { 196 mockProposalResponse.Response = nil 197 mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil) 198 }) 199 200 It("returns an error", func() { 201 err := commitReadinessChecker.ReadinessCheck() 202 Expect(err).To(MatchError("received proposal response with nil response")) 203 }) 204 }) 205 206 Context("when the endorser returns a non-success status", func() { 207 BeforeEach(func() { 208 mockProposalResponse.Response = &pb.Response{ 209 Status: 500, 210 Message: "capuccino", 211 } 212 mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil) 213 }) 214 215 It("returns an error", func() { 216 err := commitReadinessChecker.ReadinessCheck() 217 Expect(err).To(MatchError("query failed with status: 500 - capuccino")) 218 }) 219 }) 220 221 Context("when the endorser returns an unexpected result", func() { 222 BeforeEach(func() { 223 mockProposalResponse.Response = &pb.Response{ 224 Status: 200, 225 Payload: []byte("jibberish"), 226 } 227 mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil) 228 }) 229 230 It("returns an error", func() { 231 err := commitReadinessChecker.ReadinessCheck() 232 Expect(err).To(MatchError(ContainSubstring("failed to unmarshal proposal response's response payload"))) 233 }) 234 }) 235 }) 236 237 Describe("CheckCommitReadinessCmd", func() { 238 var ( 239 checkCommitReadinessCmd *cobra.Command 240 ) 241 242 BeforeEach(func() { 243 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 244 Expect(err).To(BeNil()) 245 checkCommitReadinessCmd = chaincode.CheckCommitReadinessCmd(nil, cryptoProvider) 246 checkCommitReadinessCmd.SetArgs([]string{ 247 "--channelID=testchannel", 248 "--name=testcc", 249 "--version=testversion", 250 "--sequence=1", 251 "--peerAddresses=querypeer1", 252 "--tlsRootCertFiles=tls1", 253 "--signature-policy=AND ('Org1MSP.member','Org2MSP.member')", 254 }) 255 }) 256 257 AfterEach(func() { 258 chaincode.ResetFlags() 259 }) 260 261 It("sets up the commit readiness checker and checks whether the chaincode definition is ready to commit", func() { 262 err := checkCommitReadinessCmd.Execute() 263 Expect(err).To(MatchError(ContainSubstring("failed to retrieve endorser client"))) 264 }) 265 266 Context("when the policy is invalid", func() { 267 BeforeEach(func() { 268 checkCommitReadinessCmd.SetArgs([]string{ 269 "--signature-policy=notapolicy", 270 "--channelID=testchannel", 271 "--name=testcc", 272 "--version=testversion", 273 "--sequence=1", 274 "--peerAddresses=querypeer1", 275 "--tlsRootCertFiles=tls1", 276 }) 277 }) 278 279 It("returns an error", func() { 280 err := checkCommitReadinessCmd.Execute() 281 Expect(err).To(MatchError("invalid signature policy: notapolicy")) 282 }) 283 }) 284 285 Context("when the collections config is invalid", func() { 286 BeforeEach(func() { 287 checkCommitReadinessCmd.SetArgs([]string{ 288 "--collections-config=idontexist.json", 289 "--channelID=testchannel", 290 "--name=testcc", 291 "--version=testversion", 292 "--sequence=1", 293 "--peerAddresses=querypeer1", 294 "--tlsRootCertFiles=tls1", 295 }) 296 }) 297 298 It("returns an error", func() { 299 err := checkCommitReadinessCmd.Execute() 300 Expect(err).To(MatchError("invalid collection configuration in file idontexist.json: could not read file 'idontexist.json': open idontexist.json: no such file or directory")) 301 }) 302 }) 303 }) 304 })