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