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 })