github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/chaincode/platforms/platforms_test.go (about) 1 /* 2 Copyright hechain. 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/hechain20/hechain/common/metadata" 18 "github.com/hechain20/hechain/core/chaincode/platforms" 19 "github.com/hechain20/hechain/core/chaincode/platforms/mock" 20 "github.com/hechain20/hechain/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 })