github.com/ahlemtn/fabric@v2.1.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  })