github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/lifecycle/chaincode/queryapproved_test.go (about)

     1  /*
     2  Copyright Hitachi America, Ltd. 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  	"github.com/hechain20/hechain/bccsp/sw"
    15  	"github.com/hechain20/hechain/internal/peer/lifecycle/chaincode"
    16  	"github.com/hechain20/hechain/internal/peer/lifecycle/chaincode/mock"
    17  	pb "github.com/hyperledger/fabric-protos-go/peer"
    18  	lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle"
    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("QueryApproved", func() {
    28  	Describe("ApprovedQuerier", func() {
    29  		var (
    30  			mockProposalResponse *pb.ProposalResponse
    31  			mockEndorserClient   *mock.EndorserClient
    32  			mockSigner           *mock.Signer
    33  			input                *chaincode.ApprovedQueryInput
    34  			approvedQuerier      *chaincode.ApprovedQuerier
    35  		)
    36  
    37  		BeforeEach(func() {
    38  			mockResult := &lb.QueryApprovedChaincodeDefinitionResult{
    39  				Sequence:            7,
    40  				Version:             "version_1.0",
    41  				EndorsementPlugin:   "endorsement-plugin",
    42  				ValidationPlugin:    "validation-plugin",
    43  				ValidationParameter: []byte("validation-parameter"),
    44  				InitRequired:        true,
    45  				Collections:         &pb.CollectionConfigPackage{},
    46  				Source: &lb.ChaincodeSource{
    47  					Type: &lb.ChaincodeSource_LocalPackage{
    48  						LocalPackage: &lb.ChaincodeSource_Local{
    49  							PackageId: "hash",
    50  						},
    51  					},
    52  				},
    53  			}
    54  
    55  			mockResultBytes, err := proto.Marshal(mockResult)
    56  			Expect(err).NotTo(HaveOccurred())
    57  			Expect(mockResultBytes).NotTo(BeNil())
    58  			mockProposalResponse = &pb.ProposalResponse{
    59  				Response: &pb.Response{
    60  					Status:  200,
    61  					Payload: mockResultBytes,
    62  				},
    63  			}
    64  
    65  			mockEndorserClient = &mock.EndorserClient{}
    66  			mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
    67  
    68  			mockSigner = &mock.Signer{}
    69  			buffer := gbytes.NewBuffer()
    70  
    71  			input = &chaincode.ApprovedQueryInput{
    72  				ChannelID: "test-channel",
    73  				Name:      "cc_name",
    74  			}
    75  
    76  			approvedQuerier = &chaincode.ApprovedQuerier{
    77  				Input:          input,
    78  				EndorserClient: mockEndorserClient,
    79  				Signer:         mockSigner,
    80  				Writer:         buffer,
    81  			}
    82  		})
    83  
    84  		It("queries a approved chaincode and writes the output as human readable plain-text", func() {
    85  			err := approvedQuerier.Query()
    86  			Expect(err).NotTo(HaveOccurred())
    87  			Eventually(approvedQuerier.Writer).Should(gbytes.Say("Approved chaincode definition for chaincode 'cc_name' on channel 'test-channel':\n"))
    88  			Eventually(approvedQuerier.Writer).Should(gbytes.Say("sequence: 7, version: version_1.0, init-required: true, package-id: hash, endorsement plugin: endorsement-plugin, validation plugin: validation-plugin\n"))
    89  		})
    90  
    91  		Context("when the payload contains bytes that aren't a QueryApprovedChaincodeDefinitionResult", func() {
    92  			BeforeEach(func() {
    93  				mockProposalResponse.Response = &pb.Response{
    94  					Payload: []byte("badpayloadbadpayload"),
    95  					Status:  200,
    96  				}
    97  				mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
    98  			})
    99  
   100  			It("returns an error", func() {
   101  				err := approvedQuerier.Query()
   102  				Expect(err).To(MatchError(ContainSubstring("failed to unmarshal proposal response's response payload")))
   103  			})
   104  		})
   105  
   106  		Context("when JSON-formatted output is requested", func() {
   107  			BeforeEach(func() {
   108  				approvedQuerier.Input.OutputFormat = "json"
   109  			})
   110  
   111  			It("queries the approved chaincode and writes the output as JSON", func() {
   112  				err := approvedQuerier.Query()
   113  				Expect(err).NotTo(HaveOccurred())
   114  				expectedOutput := &lb.QueryApprovedChaincodeDefinitionResult{
   115  					Sequence:            7,
   116  					Version:             "version_1.0",
   117  					EndorsementPlugin:   "endorsement-plugin",
   118  					ValidationPlugin:    "validation-plugin",
   119  					ValidationParameter: []byte("validation-parameter"),
   120  					InitRequired:        true,
   121  					Collections:         &pb.CollectionConfigPackage{},
   122  					Source: &lb.ChaincodeSource{
   123  						Type: &lb.ChaincodeSource_LocalPackage{
   124  							LocalPackage: &lb.ChaincodeSource_Local{
   125  								PackageId: "hash",
   126  							},
   127  						},
   128  					},
   129  				}
   130  				json, err := json.MarshalIndent(expectedOutput, "", "\t")
   131  				Expect(err).NotTo(HaveOccurred())
   132  				Eventually(approvedQuerier.Writer).Should(gbytes.Say(fmt.Sprintf(`\Q%s\E`, string(json))))
   133  			})
   134  		})
   135  
   136  		Context("when the chaincode source is unavailable", func() {
   137  			BeforeEach(func() {
   138  				mockResult := &lb.QueryApprovedChaincodeDefinitionResult{
   139  					Sequence:            7,
   140  					Version:             "version_1.0",
   141  					EndorsementPlugin:   "endorsement-plugin",
   142  					ValidationPlugin:    "validation-plugin",
   143  					ValidationParameter: []byte("validation-parameter"),
   144  					InitRequired:        true,
   145  					Collections:         &pb.CollectionConfigPackage{},
   146  					Source: &lb.ChaincodeSource{
   147  						Type: &lb.ChaincodeSource_Unavailable_{
   148  							Unavailable: &lb.ChaincodeSource_Unavailable{},
   149  						},
   150  					},
   151  				}
   152  				mockResultBytes, err := proto.Marshal(mockResult)
   153  				Expect(err).NotTo(HaveOccurred())
   154  				Expect(mockResultBytes).NotTo(BeNil())
   155  
   156  				mockProposalResponse = &pb.ProposalResponse{
   157  					Response: &pb.Response{
   158  						Status:  200,
   159  						Payload: mockResultBytes,
   160  					},
   161  				}
   162  				mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
   163  			})
   164  
   165  			It("queries the approved chaincode and writes the output as human readable plain-text with an empty package-id", func() {
   166  				err := approvedQuerier.Query()
   167  				Expect(err).NotTo(HaveOccurred())
   168  				Eventually(approvedQuerier.Writer).Should(gbytes.Say("Approved chaincode definition for chaincode 'cc_name' on channel 'test-channel':\n"))
   169  				Eventually(approvedQuerier.Writer).Should(gbytes.Say("sequence: 7, version: version_1.0, init-required: true, package-id: , endorsement plugin: endorsement-plugin, validation plugin: validation-plugin\n"))
   170  			})
   171  		})
   172  
   173  		Context("when the channel is not provided", func() {
   174  			BeforeEach(func() {
   175  				approvedQuerier.Input.ChannelID = ""
   176  			})
   177  
   178  			It("returns an error", func() {
   179  				err := approvedQuerier.Query()
   180  				Expect(err).To(MatchError("The required parameter 'channelID' is empty. Rerun the command with -C flag"))
   181  			})
   182  		})
   183  
   184  		Context("when the chaincode name is not provided", func() {
   185  			BeforeEach(func() {
   186  				approvedQuerier.Input.Name = ""
   187  			})
   188  
   189  			It("returns an error", func() {
   190  				err := approvedQuerier.Query()
   191  				Expect(err).To(MatchError("The required parameter 'name' is empty. Rerun the command with -n flag"))
   192  			})
   193  		})
   194  
   195  		Context("when the signer cannot be serialized", func() {
   196  			BeforeEach(func() {
   197  				mockSigner.SerializeReturns(nil, errors.New("bad serialization"))
   198  			})
   199  
   200  			It("returns an error", func() {
   201  				err := approvedQuerier.Query()
   202  				Expect(err).To(MatchError("failed to create proposal: failed to serialize identity: bad serialization"))
   203  			})
   204  		})
   205  
   206  		Context("when the signer fails to sign the proposal", func() {
   207  			BeforeEach(func() {
   208  				mockSigner.SignReturns(nil, errors.New("bad sign"))
   209  			})
   210  
   211  			It("returns an error", func() {
   212  				err := approvedQuerier.Query()
   213  				Expect(err).To(MatchError("failed to create signed proposal: bad sign"))
   214  			})
   215  		})
   216  
   217  		Context("when the endorser fails to endorse the proposal", func() {
   218  			BeforeEach(func() {
   219  				mockEndorserClient.ProcessProposalReturns(nil, errors.New("bad endorsement"))
   220  			})
   221  
   222  			It("returns an error", func() {
   223  				err := approvedQuerier.Query()
   224  				Expect(err).To(MatchError("failed to endorse proposal: bad endorsement"))
   225  			})
   226  		})
   227  
   228  		Context("when the endorser returns a nil proposal response", func() {
   229  			BeforeEach(func() {
   230  				mockProposalResponse = nil
   231  				mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
   232  			})
   233  
   234  			It("returns an error", func() {
   235  				err := approvedQuerier.Query()
   236  				Expect(err).To(MatchError("received nil proposal response"))
   237  			})
   238  		})
   239  
   240  		Context("when the endorser returns a proposal response with a nil response", func() {
   241  			BeforeEach(func() {
   242  				mockProposalResponse.Response = nil
   243  				mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
   244  			})
   245  
   246  			It("returns an error", func() {
   247  				err := approvedQuerier.Query()
   248  				Expect(err).To(MatchError("received proposal response with nil response"))
   249  			})
   250  		})
   251  
   252  		Context("when the endorser returns a non-success status", func() {
   253  			BeforeEach(func() {
   254  				mockProposalResponse.Response = &pb.Response{
   255  					Status:  500,
   256  					Message: "message",
   257  				}
   258  				mockEndorserClient.ProcessProposalReturns(mockProposalResponse, nil)
   259  			})
   260  
   261  			It("returns an error", func() {
   262  				err := approvedQuerier.Query()
   263  				Expect(err).To(MatchError("query failed with status: 500 - message"))
   264  			})
   265  		})
   266  	})
   267  
   268  	Describe("QueryApprovedCmd", func() {
   269  		var queryApprovedCmd *cobra.Command
   270  
   271  		BeforeEach(func() {
   272  			cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   273  			Expect(err).To(BeNil())
   274  			queryApprovedCmd = chaincode.QueryApprovedCmd(nil, cryptoProvider)
   275  			queryApprovedCmd.SilenceErrors = true
   276  			queryApprovedCmd.SilenceUsage = true
   277  			queryApprovedCmd.SetArgs([]string{
   278  				"--name=testcc",
   279  				"--channelID=testchannel",
   280  				"--peerAddresses=queryapprovedpeer1",
   281  				"--tlsRootCertFiles=tls1",
   282  			})
   283  		})
   284  
   285  		AfterEach(func() {
   286  			chaincode.ResetFlags()
   287  		})
   288  
   289  		It("attempts to connect to the endorser", func() {
   290  			err := queryApprovedCmd.Execute()
   291  			Expect(err).To(MatchError(ContainSubstring("failed to retrieve endorser client")))
   292  		})
   293  
   294  		Context("when more than one peer address is provided", func() {
   295  			BeforeEach(func() {
   296  				queryApprovedCmd.SetArgs([]string{
   297  					"--name=testcc",
   298  					"--channelID=testchannel",
   299  					"--peerAddresses=queryapprovedpeer1",
   300  					"--tlsRootCertFiles=tls1",
   301  					"--peerAddresses=queryapprovedpeer2",
   302  					"--tlsRootCertFiles=tls2",
   303  				})
   304  			})
   305  
   306  			It("returns an error", func() {
   307  				err := queryApprovedCmd.Execute()
   308  				Expect(err).To(MatchError(ContainSubstring("failed to validate peer connection parameters")))
   309  			})
   310  		})
   311  	})
   312  })