github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/core/chaincode/platforms/platforms_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package platforms_test
     8  
     9  import (
    10  	"archive/tar"
    11  	"bytes"
    12  	"errors"
    13  	"fmt"
    14  	"io/ioutil"
    15  
    16  	docker "github.com/fsouza/go-dockerclient"
    17  	"github.com/hyperledger/fabric/common/metadata"
    18  	"github.com/hyperledger/fabric/core/chaincode/platforms"
    19  	"github.com/hyperledger/fabric/core/chaincode/platforms/mock"
    20  	"github.com/hyperledger/fabric/core/chaincode/platforms/util"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  )
    24  
    25  var _ = Describe("Platforms", func() {
    26  	var (
    27  		registry     *platforms.Registry
    28  		fakePlatform *mock.Platform
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		fakePlatform = &mock.Platform{}
    33  		registry = &platforms.Registry{
    34  			Platforms: map[string]platforms.Platform{
    35  				"fakeType": fakePlatform,
    36  			},
    37  		}
    38  	})
    39  
    40  	Describe("GenerateDockerfile", func() {
    41  		It("calls the underlying platform, then appends some boilerplate", func() {
    42  			fakePlatform.GenerateDockerfileReturns("docker-header", nil)
    43  			df, err := registry.GenerateDockerfile("fakeType")
    44  			Expect(err).NotTo(HaveOccurred())
    45  			expectedDockerfile := fmt.Sprintf(`docker-header
    46  LABEL org.hyperledger.fabric.chaincode.type="fakeType" \
    47        org.hyperledger.fabric.version="%s"
    48  ENV CORE_CHAINCODE_BUILDLEVEL=%s`, metadata.Version, metadata.Version)
    49  			Expect(df).To(Equal(expectedDockerfile))
    50  		})
    51  
    52  		Context("when the underlying platform returns an error", func() {
    53  			It("returns the error", func() {
    54  				fakePlatform.GenerateDockerfileReturns("docker-header", errors.New("fake-error"))
    55  				_, err := registry.GenerateDockerfile("fakeType")
    56  				Expect(err).To(MatchError("Failed to generate platform-specific Dockerfile: fake-error"))
    57  			})
    58  		})
    59  
    60  		Context("when the platform is unknown", func() {
    61  			It("returns an error", func() {
    62  				df, err := registry.GenerateDockerfile("badType")
    63  				Expect(df).To(BeEmpty())
    64  				Expect(err).To(MatchError("Unknown chaincodeType: badType"))
    65  			})
    66  		})
    67  	})
    68  
    69  	Describe("the pieces which deal with packaging", func() {
    70  		var (
    71  			buf    *bytes.Buffer
    72  			tw     *tar.Writer
    73  			pw     *mock.PackageWriter
    74  			client *docker.Client
    75  		)
    76  
    77  		BeforeEach(func() {
    78  			buf = &bytes.Buffer{}
    79  			tw = tar.NewWriter(buf)
    80  			pw = &mock.PackageWriter{}
    81  			registry.PackageWriter = pw
    82  			registry.DockerBuild = func(util.DockerBuildOptions, *docker.Client) error { return nil }
    83  			dockerClient, err := docker.NewClientFromEnv()
    84  			Expect(err).NotTo(HaveOccurred())
    85  			client = dockerClient
    86  		})
    87  
    88  		Describe("StreamDockerBuild", func() {
    89  			AfterEach(func() {
    90  				tw.Close()
    91  			})
    92  
    93  			It("adds the specified files to the tar, then has the underlying platform add its files", func() {
    94  				fileMap := map[string][]byte{
    95  					"foo": []byte("foo-bytes"),
    96  				}
    97  				err := registry.StreamDockerBuild("fakeType", "", nil, fileMap, tw, client)
    98  				Expect(err).NotTo(HaveOccurred())
    99  				Expect(pw.WriteCallCount()).To(Equal(1))
   100  				name, data, writer := pw.WriteArgsForCall(0)
   101  				Expect(name).To(Equal("foo"))
   102  				Expect(data).To(Equal([]byte("foo-bytes")))
   103  				Expect(writer).To(Equal(tw))
   104  				Expect(fakePlatform.DockerBuildOptionsCallCount()).To(Equal(1))
   105  			})
   106  
   107  			Context("when the platform is unknown", func() {
   108  				It("returns an error", func() {
   109  					err := registry.StreamDockerBuild("badType", "", nil, nil, tw, client)
   110  					Expect(err).To(MatchError("could not find platform of type: badType"))
   111  				})
   112  			})
   113  
   114  			Context("when the writer fails", func() {
   115  				It("returns an error", func() {
   116  					fileMap := map[string][]byte{
   117  						"foo": []byte("foo-bytes"),
   118  					}
   119  
   120  					pw.WriteReturns(errors.New("fake-error"))
   121  					err := registry.StreamDockerBuild("fakeType", "", nil, fileMap, tw, client)
   122  					Expect(err).To(MatchError("Failed to inject \"foo\": fake-error"))
   123  					Expect(pw.WriteCallCount()).To(Equal(1))
   124  				})
   125  			})
   126  
   127  			Context("when the underlying platform fails", func() {
   128  				It("returns an error", func() {
   129  					fakePlatform.DockerBuildOptionsReturns(util.DockerBuildOptions{}, errors.New("fake-error"))
   130  					err := registry.StreamDockerBuild("fakeType", "", nil, nil, tw, client)
   131  					Expect(err).To(MatchError("platform failed to create docker build options: fake-error"))
   132  				})
   133  			})
   134  
   135  			Context("when the docker build fails", func() {
   136  				It("returns an error", func() {
   137  					registry.DockerBuild = func(util.DockerBuildOptions, *docker.Client) error { return errors.New("kaboom") }
   138  					err := registry.StreamDockerBuild("fakeType", "", nil, nil, tw, client)
   139  					Expect(err).To(MatchError("docker build failed: kaboom"))
   140  				})
   141  			})
   142  		})
   143  
   144  		Describe("GenerateDockerBuild", func() {
   145  			It("creates a stream for the package", func() {
   146  				reader, err := registry.GenerateDockerBuild("fakeType", "", nil, client)
   147  				Expect(err).NotTo(HaveOccurred())
   148  				_, err = ioutil.ReadAll(reader)
   149  				Expect(err).NotTo(HaveOccurred())
   150  			})
   151  
   152  			Context("when there is a problem generating the dockerfile", func() {
   153  				It("returns an error", func() {
   154  					fakePlatform.GenerateDockerfileReturns("docker-header", errors.New("fake-error"))
   155  					_, err := registry.GenerateDockerBuild("fakeType", "", nil, client)
   156  					Expect(err).To(MatchError("Failed to generate a Dockerfile: Failed to generate platform-specific Dockerfile: fake-error"))
   157  				})
   158  			})
   159  
   160  			Context("when there is a problem streaming the dockerbuild", func() {
   161  				It("closes the reader with an error", func() {
   162  					pw.WriteReturns(errors.New("fake-error"))
   163  					reader, err := registry.GenerateDockerBuild("fakeType", "", nil, client)
   164  					Expect(err).NotTo(HaveOccurred())
   165  					_, err = ioutil.ReadAll(reader)
   166  					Expect(err).To(MatchError("Failed to inject \"Dockerfile\": fake-error"))
   167  				})
   168  			})
   169  		})
   170  	})
   171  
   172  	Describe("NewRegistry", func() {
   173  		It("initializes with the known platform types and util writer", func() {
   174  			fakePlatformFoo := &mock.Platform{}
   175  			fakePlatformFoo.NameReturns("foo")
   176  			fakePlatformBar := &mock.Platform{}
   177  			fakePlatformBar.NameReturns("bar")
   178  
   179  			registry = platforms.NewRegistry(fakePlatformFoo, fakePlatformBar)
   180  
   181  			Expect(registry.Platforms).To(Equal(map[string]platforms.Platform{
   182  				"foo": fakePlatformFoo,
   183  				"bar": fakePlatformBar,
   184  			}))
   185  		})
   186  
   187  		Context("when two platforms report the same name", func() {
   188  			It("panics", func() {
   189  				fakePlatformFoo1 := &mock.Platform{}
   190  				fakePlatformFoo1.NameReturns("foo")
   191  				fakePlatformFoo2 := &mock.Platform{}
   192  				fakePlatformFoo2.NameReturns("foo")
   193  				Expect(func() { platforms.NewRegistry(fakePlatformFoo1, fakePlatformFoo2) }).To(Panic())
   194  			})
   195  		})
   196  	})
   197  
   198  	Describe("PackageWriterWrapper", func() {
   199  		It("calls through to the underlying function", func() {
   200  			pw := &mock.PackageWriter{}
   201  			pw.WriteReturns(errors.New("fake-error"))
   202  			tw := &tar.Writer{}
   203  			pww := platforms.PackageWriterWrapper(pw.Write)
   204  			err := pww.Write("name", []byte("payload"), tw)
   205  			Expect(err).To(MatchError(errors.New("fake-error")))
   206  			Expect(pw.WriteCallCount()).To(Equal(1))
   207  			name, payload, tw2 := pw.WriteArgsForCall(0)
   208  			Expect(name).To(Equal("name"))
   209  			Expect(payload).To(Equal([]byte("payload")))
   210  			Expect(tw2).To(Equal(tw))
   211  		})
   212  	})
   213  })