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