github.com/anjalikarhana/fabric@v2.1.1+incompatible/internal/peer/lifecycle/chaincode/package_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package chaincode_test
     8  
     9  import (
    10  	"archive/tar"
    11  	"bytes"
    12  	"compress/gzip"
    13  	"io"
    14  	"io/ioutil"
    15  	"os"
    16  	"path/filepath"
    17  
    18  	"github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode"
    19  	"github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode/mock"
    20  	"github.com/pkg/errors"
    21  	"github.com/spf13/cobra"
    22  
    23  	. "github.com/onsi/ginkgo"
    24  	. "github.com/onsi/gomega"
    25  )
    26  
    27  var _ = Describe("Package", func() {
    28  	Describe("Packager", func() {
    29  		var (
    30  			mockPlatformRegistry *mock.PlatformRegistry
    31  			mockWriter           *mock.Writer
    32  			input                *chaincode.PackageInput
    33  			packager             *chaincode.Packager
    34  		)
    35  
    36  		BeforeEach(func() {
    37  			mockPlatformRegistry = &mock.PlatformRegistry{}
    38  			mockPlatformRegistry.NormalizePathReturns("normalizedPath", nil)
    39  
    40  			input = &chaincode.PackageInput{
    41  				OutputFile: "testDir/testPackage",
    42  				Path:       "testPath",
    43  				Type:       "testType",
    44  				Label:      "testLabel",
    45  			}
    46  
    47  			mockWriter = &mock.Writer{}
    48  
    49  			packager = &chaincode.Packager{
    50  				PlatformRegistry: mockPlatformRegistry,
    51  				Writer:           mockWriter,
    52  				Input:            input,
    53  			}
    54  		})
    55  
    56  		It("packages chaincodes", func() {
    57  			err := packager.Package()
    58  			Expect(err).NotTo(HaveOccurred())
    59  
    60  			Expect(mockPlatformRegistry.NormalizePathCallCount()).To(Equal(1))
    61  			ccType, path := mockPlatformRegistry.NormalizePathArgsForCall(0)
    62  			Expect(ccType).To(Equal("TESTTYPE"))
    63  			Expect(path).To(Equal("testPath"))
    64  
    65  			Expect(mockPlatformRegistry.GetDeploymentPayloadCallCount()).To(Equal(1))
    66  			ccType, path = mockPlatformRegistry.GetDeploymentPayloadArgsForCall(0)
    67  			Expect(ccType).To(Equal("TESTTYPE"))
    68  			Expect(path).To(Equal("testPath"))
    69  
    70  			Expect(mockWriter.WriteFileCallCount()).To(Equal(1))
    71  			dir, name, pkgTarGzBytes := mockWriter.WriteFileArgsForCall(0)
    72  			wd, err := os.Getwd()
    73  			Expect(err).NotTo(HaveOccurred())
    74  			Expect(dir).To(Equal(filepath.Join(wd, "testDir")))
    75  			Expect(name).To(Equal("testPackage"))
    76  			Expect(pkgTarGzBytes).NotTo(BeNil())
    77  
    78  			metadata, err := readMetadataFromBytes(pkgTarGzBytes)
    79  			Expect(err).NotTo(HaveOccurred())
    80  			Expect(metadata).To(MatchJSON(`{"path":"normalizedPath","type":"testType","label":"testLabel"}`))
    81  		})
    82  
    83  		Context("when the path is not provided", func() {
    84  			BeforeEach(func() {
    85  				input.Path = ""
    86  			})
    87  
    88  			It("returns an error", func() {
    89  				err := packager.Package()
    90  				Expect(err).To(MatchError("chaincode path must be specified"))
    91  			})
    92  		})
    93  
    94  		Context("when the type is not provided", func() {
    95  			BeforeEach(func() {
    96  				input.Type = ""
    97  			})
    98  
    99  			It("returns an error", func() {
   100  				err := packager.Package()
   101  				Expect(err).To(MatchError("chaincode language must be specified"))
   102  			})
   103  		})
   104  
   105  		Context("when the output file is not provided", func() {
   106  			BeforeEach(func() {
   107  				input.OutputFile = ""
   108  			})
   109  
   110  			It("returns an error", func() {
   111  				err := packager.Package()
   112  				Expect(err).To(MatchError("output file must be specified"))
   113  			})
   114  		})
   115  
   116  		Context("when the label is not provided", func() {
   117  			BeforeEach(func() {
   118  				input.Label = ""
   119  			})
   120  
   121  			It("returns an error", func() {
   122  				err := packager.Package()
   123  				Expect(err).To(MatchError("package label must be specified"))
   124  			})
   125  		})
   126  
   127  		Context("when the label is invalid", func() {
   128  			BeforeEach(func() {
   129  				input.Label = "label with spaces"
   130  			})
   131  
   132  			It("returns an error", func() {
   133  				err := packager.Package()
   134  				Expect(err).To(MatchError("invalid label 'label with spaces'. Label must be non-empty, can only consist of alphanumerics, symbols from '.+-_', and can only begin with alphanumerics"))
   135  			})
   136  		})
   137  
   138  		Context("when the platform registry fails to normalize the path", func() {
   139  			BeforeEach(func() {
   140  				mockPlatformRegistry.NormalizePathReturns("", errors.New("cortado"))
   141  			})
   142  
   143  			It("returns an error", func() {
   144  				err := packager.Package()
   145  				Expect(err).To(MatchError("failed to normalize chaincode path: cortado"))
   146  			})
   147  		})
   148  
   149  		Context("when the platform registry fails to get the deployment payload", func() {
   150  			BeforeEach(func() {
   151  				mockPlatformRegistry.GetDeploymentPayloadReturns(nil, errors.New("americano"))
   152  			})
   153  
   154  			It("returns an error", func() {
   155  				err := packager.Package()
   156  				Expect(err).To(MatchError("error getting chaincode bytes: americano"))
   157  			})
   158  		})
   159  
   160  		Context("when writing the file fails", func() {
   161  			BeforeEach(func() {
   162  				mockWriter.WriteFileReturns(errors.New("espresso"))
   163  			})
   164  
   165  			It("returns an error", func() {
   166  				err := packager.Package()
   167  				Expect(err).To(MatchError("error writing chaincode package to testDir/testPackage: espresso"))
   168  			})
   169  		})
   170  	})
   171  
   172  	Describe("PackageCmd", func() {
   173  		var (
   174  			packageCmd *cobra.Command
   175  		)
   176  
   177  		BeforeEach(func() {
   178  			packageCmd = chaincode.PackageCmd(nil)
   179  			packageCmd.SetArgs([]string{
   180  				"testPackage",
   181  				"--path=testPath",
   182  				"--lang=golang",
   183  				"--label=testLabel",
   184  			})
   185  		})
   186  
   187  		It("sets up the packager and attempts to package the chaincode", func() {
   188  			err := packageCmd.Execute()
   189  			Expect(err).To(MatchError(ContainSubstring("error getting chaincode bytes")))
   190  		})
   191  
   192  		Context("when more than one argument is provided", func() {
   193  			BeforeEach(func() {
   194  				packageCmd = chaincode.PackageCmd(nil)
   195  				packageCmd.SetArgs([]string{
   196  					"testPackage",
   197  					"whatthe",
   198  				})
   199  			})
   200  
   201  			It("returns an error", func() {
   202  				err := packageCmd.Execute()
   203  				Expect(err).To(MatchError("invalid number of args. expected only the output file"))
   204  			})
   205  		})
   206  
   207  		Context("when no argument is provided", func() {
   208  			BeforeEach(func() {
   209  				packageCmd = chaincode.PackageCmd(nil)
   210  				packageCmd.SetArgs([]string{})
   211  			})
   212  
   213  			It("returns an error", func() {
   214  				err := packageCmd.Execute()
   215  				Expect(err).To(MatchError("invalid number of args. expected only the output file"))
   216  			})
   217  		})
   218  	})
   219  })
   220  
   221  func readMetadataFromBytes(pkgTarGzBytes []byte) ([]byte, error) {
   222  	buffer := bytes.NewBuffer(pkgTarGzBytes)
   223  	gzr, err := gzip.NewReader(buffer)
   224  	Expect(err).NotTo(HaveOccurred())
   225  	defer gzr.Close()
   226  	tr := tar.NewReader(gzr)
   227  	for {
   228  		header, err := tr.Next()
   229  		if err == io.EOF {
   230  			break
   231  		}
   232  		if err != nil {
   233  			return nil, err
   234  		}
   235  		if header.Name == "metadata.json" {
   236  			return ioutil.ReadAll(tr)
   237  		}
   238  	}
   239  	return nil, errors.New("metadata.json not found")
   240  }