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