github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/core/container/container_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package container_test 8 9 import ( 10 "bytes" 11 "io/ioutil" 12 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 16 "github.com/hyperledger/fabric/core/chaincode/persistence" 17 "github.com/hyperledger/fabric/core/container" 18 "github.com/hyperledger/fabric/core/container/ccintf" 19 "github.com/hyperledger/fabric/core/container/mock" 20 "github.com/pkg/errors" 21 ) 22 23 var _ = Describe("Router", func() { 24 var ( 25 fakeDockerVM *mock.VM 26 fakeExternalVM *mock.VM 27 fakePackageProvider *mock.PackageProvider 28 fakeInstance *mock.Instance 29 router *container.Router 30 ) 31 32 BeforeEach(func() { 33 fakeDockerVM = &mock.VM{} 34 fakeExternalVM = &mock.VM{} 35 fakeInstance = &mock.Instance{} 36 fakePackageProvider = &mock.PackageProvider{} 37 fakePackageProvider.GetChaincodePackageReturns( 38 &persistence.ChaincodePackageMetadata{ 39 Type: "package-type", 40 Path: "package-path", 41 }, 42 ioutil.NopCloser(bytes.NewBuffer([]byte("code-bytes"))), 43 nil, 44 ) 45 46 router = &container.Router{ 47 DockerVM: fakeDockerVM, 48 ExternalVM: fakeExternalVM, 49 PackageProvider: fakePackageProvider, 50 } 51 }) 52 53 Describe("Build", func() { 54 BeforeEach(func() { 55 fakeExternalVM.BuildReturns(fakeInstance, nil) 56 }) 57 58 It("calls the external builder with the correct args", func() { 59 err := router.Build("package-id") 60 Expect(err).NotTo(HaveOccurred()) 61 62 Expect(fakeExternalVM.BuildCallCount()).To(Equal(1)) 63 ccid, md, codeStream := fakeExternalVM.BuildArgsForCall(0) 64 Expect(ccid).To(Equal("package-id")) 65 Expect(md).To(Equal(&persistence.ChaincodePackageMetadata{ 66 Type: "package-type", 67 Path: "package-path", 68 })) 69 codePackage, err := ioutil.ReadAll(codeStream) 70 Expect(err).NotTo(HaveOccurred()) 71 Expect(codePackage).To(Equal([]byte("code-bytes"))) 72 }) 73 74 Context("when the package provider returns an error before calling the external builder", func() { 75 BeforeEach(func() { 76 fakePackageProvider.GetChaincodePackageReturns(nil, nil, errors.New("fake-package-error")) 77 }) 78 79 It("wraps and returns the error", func() { 80 err := router.Build("package-id") 81 Expect(err).To(MatchError("failed to get chaincode package for external build: fake-package-error")) 82 }) 83 84 It("does not call the external builder", func() { 85 router.Build("package-id") 86 Expect(fakeExternalVM.BuildCallCount()).To(Equal(0)) 87 }) 88 }) 89 90 Context("when the external builder returns an error", func() { 91 BeforeEach(func() { 92 fakeExternalVM.BuildReturns(nil, errors.New("fake-external-error")) 93 fakeDockerVM.BuildReturns(fakeInstance, nil) 94 }) 95 96 It("wraps and returns the error", func() { 97 err := router.Build("package-id") 98 Expect(err).To(MatchError("external builder failed: fake-external-error")) 99 }) 100 }) 101 102 Context("when the external builder returns successfully with an instance", func() { 103 It("does not call the docker builder", func() { 104 err := router.Build("package-id") 105 Expect(err).NotTo(HaveOccurred()) 106 107 Expect(fakeExternalVM.BuildCallCount()).To(Equal(1)) 108 Expect(fakeDockerVM.BuildCallCount()).To(Equal(0)) 109 }) 110 }) 111 112 Context("when the exxternal builder returns a nil instance", func() { 113 BeforeEach(func() { 114 fakeExternalVM.BuildReturns(nil, nil) 115 fakeDockerVM.BuildReturns(fakeInstance, nil) 116 }) 117 118 It("falls back to the docker impl", func() { 119 err := router.Build("package-id") 120 Expect(err).NotTo(HaveOccurred()) 121 122 Expect(fakeDockerVM.BuildCallCount()).To(Equal(1)) 123 ccid, md, codeStream := fakeDockerVM.BuildArgsForCall(0) 124 Expect(ccid).To(Equal("package-id")) 125 Expect(md).To(Equal(&persistence.ChaincodePackageMetadata{ 126 Type: "package-type", 127 Path: "package-path", 128 })) 129 codePackage, err := ioutil.ReadAll(codeStream) 130 Expect(err).NotTo(HaveOccurred()) 131 Expect(codePackage).To(Equal([]byte("code-bytes"))) 132 }) 133 134 Context("when the package provider returns an error before calling the docker builder", func() { 135 BeforeEach(func() { 136 fakePackageProvider.GetChaincodePackageReturnsOnCall(1, nil, nil, errors.New("fake-package-error")) 137 }) 138 139 It("wraps and returns the error", func() { 140 err := router.Build("package-id") 141 Expect(err).To(MatchError("failed to get chaincode package for docker build: fake-package-error")) 142 }) 143 }) 144 }) 145 146 Context("when an external builder is not provided", func() { 147 BeforeEach(func() { 148 router.ExternalVM = nil 149 fakeDockerVM.BuildReturns(fakeInstance, nil) 150 }) 151 152 It("uses the docker vm builder", func() { 153 err := router.Build("package-id") 154 Expect(err).NotTo(HaveOccurred()) 155 Expect(fakeDockerVM.BuildCallCount()).To(Equal(1)) 156 }) 157 }) 158 }) 159 160 Describe("Post-build operations", func() { 161 BeforeEach(func() { 162 fakeExternalVM.BuildReturns(fakeInstance, nil) 163 err := router.Build("fake-id") 164 Expect(err).NotTo(HaveOccurred()) 165 }) 166 167 Describe("Start", func() { 168 BeforeEach(func() { 169 fakeInstance.StartReturns(errors.New("fake-start-error")) 170 }) 171 172 It("passes through to the docker impl", func() { 173 err := router.Start( 174 "fake-id", 175 &ccintf.PeerConnection{ 176 Address: "peer-address", 177 TLSConfig: &ccintf.TLSConfig{ 178 ClientKey: []byte("key"), 179 ClientCert: []byte("cert"), 180 RootCert: []byte("root"), 181 }, 182 }, 183 ) 184 185 Expect(err).To(MatchError("fake-start-error")) 186 Expect(fakeInstance.StartCallCount()).To(Equal(1)) 187 Expect(fakeInstance.StartArgsForCall(0)).To(Equal(&ccintf.PeerConnection{ 188 Address: "peer-address", 189 TLSConfig: &ccintf.TLSConfig{ 190 ClientKey: []byte("key"), 191 ClientCert: []byte("cert"), 192 RootCert: []byte("root"), 193 }, 194 })) 195 }) 196 197 Context("when the chaincode has not yet been built", func() { 198 It("returns an error", func() { 199 err := router.Start( 200 "missing-name", 201 &ccintf.PeerConnection{ 202 Address: "peer-address", 203 }, 204 ) 205 Expect(err).To(MatchError("instance has not yet been built, cannot be started")) 206 }) 207 }) 208 }) 209 210 Describe("Stop", func() { 211 BeforeEach(func() { 212 fakeInstance.StopReturns(errors.New("Boo")) 213 }) 214 215 It("passes through to the docker impl", func() { 216 err := router.Stop("fake-id") 217 Expect(err).To(MatchError("Boo")) 218 Expect(fakeInstance.StopCallCount()).To(Equal(1)) 219 }) 220 221 Context("when the chaincode has not yet been built", func() { 222 It("returns an error", func() { 223 err := router.Stop("missing-name") 224 Expect(err).To(MatchError("instance has not yet been built, cannot be stopped")) 225 }) 226 }) 227 }) 228 229 Describe("Wait", func() { 230 BeforeEach(func() { 231 fakeInstance.WaitReturns(7, errors.New("fake-wait-error")) 232 }) 233 234 It("passes through to the docker impl", func() { 235 res, err := router.Wait( 236 "fake-id", 237 ) 238 Expect(res).To(Equal(7)) 239 Expect(err).To(MatchError("fake-wait-error")) 240 Expect(fakeInstance.WaitCallCount()).To(Equal(1)) 241 }) 242 243 Context("when the chaincode has not yet been built", func() { 244 It("returns an error", func() { 245 _, err := router.Wait("missing-name") 246 Expect(err).To(MatchError("instance has not yet been built, cannot wait")) 247 }) 248 }) 249 }) 250 }) 251 })