github.com/binyushen/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 })