github.com/ewagmig/fabric@v2.1.1+incompatible/core/chaincode/lifecycle/event_broker_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lifecycle_test
     8  
     9  import (
    10  	"archive/tar"
    11  	"bytes"
    12  	"io"
    13  
    14  	lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle"
    15  	"github.com/hyperledger/fabric/core/chaincode/lifecycle"
    16  	"github.com/hyperledger/fabric/core/chaincode/lifecycle/mock"
    17  	"github.com/hyperledger/fabric/core/chaincode/persistence"
    18  	"github.com/hyperledger/fabric/core/container/externalbuilder"
    19  	"github.com/hyperledger/fabric/core/ledger"
    20  	ledgermock "github.com/hyperledger/fabric/core/ledger/mock"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  	"github.com/pkg/errors"
    24  )
    25  
    26  var _ = Describe("EventBroker", func() {
    27  	var (
    28  		fakeListener       *ledgermock.ChaincodeLifecycleEventListener
    29  		chaincodeStore     *mock.ChaincodeStore
    30  		pkgParser          *mock.PackageParser
    31  		eventBroker        *lifecycle.EventBroker
    32  		cachedChaincodeDef *lifecycle.CachedChaincodeDefinition
    33  		localChaincode     *lifecycle.LocalChaincode
    34  		ebMetadata         *externalbuilder.MetadataProvider
    35  	)
    36  
    37  	BeforeEach(func() {
    38  		fakeListener = &ledgermock.ChaincodeLifecycleEventListener{}
    39  		chaincodeStore = &mock.ChaincodeStore{}
    40  		pkgParser = &mock.PackageParser{}
    41  		ebMetadata = &externalbuilder.MetadataProvider{
    42  			DurablePath: "testdata",
    43  		}
    44  		eventBroker = lifecycle.NewEventBroker(chaincodeStore, pkgParser, ebMetadata)
    45  		cachedChaincodeDef = &lifecycle.CachedChaincodeDefinition{}
    46  		localChaincode = &lifecycle.LocalChaincode{
    47  			Info: &lifecycle.ChaincodeInstallInfo{
    48  				PackageID: "PackageID",
    49  			},
    50  			References: make(map[string]map[string]*lifecycle.CachedChaincodeDefinition),
    51  		}
    52  		eventBroker.RegisterListener("channel-1", fakeListener)
    53  		pkgParser.ParseReturns(&persistence.ChaincodePackage{
    54  			DBArtifacts: []byte("db-artifacts"),
    55  		}, nil)
    56  	})
    57  
    58  	Context("when chaincode is only approved", func() {
    59  		BeforeEach(func() {
    60  			cachedChaincodeDef.Approved = true
    61  		})
    62  
    63  		It("does not invoke listener", func() {
    64  			eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
    65  			eventBroker.ApproveOrDefineCommitted("channel-1")
    66  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
    67  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
    68  		})
    69  	})
    70  
    71  	Context("when chaincode is only defined", func() {
    72  		BeforeEach(func() {
    73  			cachedChaincodeDef.Definition = &lifecycle.ChaincodeDefinition{}
    74  		})
    75  
    76  		It("does not invoke listener", func() {
    77  			eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
    78  			eventBroker.ApproveOrDefineCommitted("channel-1")
    79  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
    80  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
    81  		})
    82  	})
    83  
    84  	Context("when chaincode is approved and defined", func() {
    85  		BeforeEach(func() {
    86  			cachedChaincodeDef.Approved = true
    87  			cachedChaincodeDef.Definition = &lifecycle.ChaincodeDefinition{}
    88  		})
    89  
    90  		It("does not invoke listener", func() {
    91  			eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
    92  			eventBroker.ApproveOrDefineCommitted("channel-1")
    93  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
    94  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
    95  		})
    96  	})
    97  
    98  	Context("when chaincode is only installed", func() {
    99  		It("does not invoke listener", func() {
   100  			eventBroker.ProcessInstallEvent(localChaincode)
   101  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
   102  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
   103  		})
   104  	})
   105  
   106  	Context("when chaincode is first installed and then defined", func() {
   107  		BeforeEach(func() {
   108  			cachedChaincodeDef.InstallInfo = &lifecycle.ChaincodeInstallInfo{}
   109  			cachedChaincodeDef.Definition = &lifecycle.ChaincodeDefinition{}
   110  		})
   111  
   112  		It("does not invoke listener", func() {
   113  			eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
   114  			eventBroker.ApproveOrDefineCommitted("channel-1")
   115  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
   116  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
   117  		})
   118  	})
   119  
   120  	Context("when chaincode is first defined and then installed", func() {
   121  		BeforeEach(func() {
   122  			cachedChaincodeDef.InstallInfo = &lifecycle.ChaincodeInstallInfo{}
   123  			cachedChaincodeDef.Definition = &lifecycle.ChaincodeDefinition{}
   124  			localChaincode.References["channel-1"] = map[string]*lifecycle.CachedChaincodeDefinition{
   125  				"chaincode-1": cachedChaincodeDef,
   126  			}
   127  		})
   128  
   129  		It("does not invoke listener", func() {
   130  			eventBroker.ProcessInstallEvent(localChaincode)
   131  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
   132  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
   133  		})
   134  	})
   135  
   136  	Context("when chaincode is approved, defined, and installed", func() {
   137  		BeforeEach(func() {
   138  			cachedChaincodeDef.Approved = true
   139  			cachedChaincodeDef.Definition = &lifecycle.ChaincodeDefinition{
   140  				EndorsementInfo: &lb.ChaincodeEndorsementInfo{
   141  					Version: "version-1",
   142  				},
   143  			}
   144  			cachedChaincodeDef.InstallInfo = localChaincode.Info
   145  			localChaincode.References["channel-1"] = map[string]*lifecycle.CachedChaincodeDefinition{
   146  				"chaincode-1": cachedChaincodeDef,
   147  			}
   148  		})
   149  
   150  		It("invokes listener when ProcessInstallEvent is called", func() {
   151  			eventBroker.ProcessInstallEvent(localChaincode)
   152  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(1))
   153  			def, md := fakeListener.HandleChaincodeDeployArgsForCall(0)
   154  			Expect(def).To(Equal(&ledger.ChaincodeDefinition{
   155  				Name:    "chaincode-1",
   156  				Hash:    []byte("PackageID"),
   157  				Version: "version-1",
   158  			}))
   159  			Expect(md).To(Equal([]byte("db-artifacts")))
   160  
   161  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(1))
   162  		})
   163  
   164  		It("invokes listener when ProcessApproveOrDefineEvent is called", func() {
   165  			eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
   166  			Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(1))
   167  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
   168  			eventBroker.ApproveOrDefineCommitted("channel-1")
   169  			Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(1))
   170  		})
   171  
   172  		When("the metadata is defined by the external builders", func() {
   173  			BeforeEach(func() {
   174  				localChaincode.Info.PackageID = "external-built-cc"
   175  			})
   176  
   177  			It("does not invoke listener", func() {
   178  				eventBroker.ProcessInstallEvent(localChaincode)
   179  				Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(1))
   180  				def, md := fakeListener.HandleChaincodeDeployArgsForCall(0)
   181  				Expect(def).To(Equal(&ledger.ChaincodeDefinition{
   182  					Name:    "chaincode-1",
   183  					Hash:    []byte("external-built-cc"),
   184  					Version: "version-1",
   185  				}))
   186  
   187  				mdContents := map[string]struct{}{}
   188  				tr := tar.NewReader(bytes.NewBuffer(md))
   189  				for {
   190  					hdr, err := tr.Next()
   191  					if err == io.EOF {
   192  						break
   193  					}
   194  					Expect(err).NotTo(HaveOccurred())
   195  					mdContents[hdr.Name] = struct{}{}
   196  				}
   197  				Expect(mdContents).To(HaveKey("META-INF/"))
   198  				Expect(mdContents).To(HaveKey("META-INF/index.json"))
   199  			})
   200  		})
   201  
   202  		Context("when chaincode store returns error", func() {
   203  			BeforeEach(func() {
   204  				chaincodeStore.LoadReturns(nil, errors.New("loading-error"))
   205  			})
   206  
   207  			It("does not invoke listener", func() {
   208  				eventBroker.ProcessInstallEvent(localChaincode)
   209  				eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
   210  				eventBroker.ApproveOrDefineCommitted("channel-1")
   211  				Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
   212  				Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
   213  			})
   214  		})
   215  
   216  		Context("when chaincode package parser returns error", func() {
   217  			BeforeEach(func() {
   218  				pkgParser.ParseReturns(nil, errors.New("parsing-error"))
   219  			})
   220  
   221  			It("does not invoke listener", func() {
   222  				eventBroker.ProcessInstallEvent(localChaincode)
   223  				eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
   224  				eventBroker.ApproveOrDefineCommitted("channel-1")
   225  				Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(0))
   226  				Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(0))
   227  			})
   228  		})
   229  
   230  		Context("when listener returns error", func() {
   231  			BeforeEach(func() {
   232  				fakeListener.HandleChaincodeDeployReturns(errors.New("listener-error"))
   233  			})
   234  
   235  			It("still invokes ChaincodeDeployDone() function on listener", func() {
   236  				eventBroker.ProcessInstallEvent(localChaincode)
   237  				Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(1))
   238  				Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(1))
   239  
   240  				eventBroker.ProcessApproveOrDefineEvent("channel-1", "chaincode-1", cachedChaincodeDef)
   241  				Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(2))
   242  				Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(1))
   243  				eventBroker.ApproveOrDefineCommitted("channel-1")
   244  				Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(2))
   245  			})
   246  		})
   247  	})
   248  })