239 lines
6.1 KiB
Go
239 lines
6.1 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package chaincode_test
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"compress/gzip"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode"
|
|
"github.com/hyperledger/fabric/internal/peer/lifecycle/chaincode/mock"
|
|
"github.com/pkg/errors"
|
|
"github.com/spf13/cobra"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Package", func() {
|
|
Describe("Packager", func() {
|
|
var (
|
|
mockPlatformRegistry *mock.PlatformRegistry
|
|
mockWriter *mock.Writer
|
|
input *chaincode.PackageInput
|
|
packager *chaincode.Packager
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
mockPlatformRegistry = &mock.PlatformRegistry{}
|
|
mockPlatformRegistry.NormalizePathReturns("normalizedPath", nil)
|
|
|
|
input = &chaincode.PackageInput{
|
|
OutputFile: "testDir/testPackage",
|
|
Path: "testPath",
|
|
Type: "testType",
|
|
Label: "testLabel",
|
|
}
|
|
|
|
mockWriter = &mock.Writer{}
|
|
|
|
packager = &chaincode.Packager{
|
|
PlatformRegistry: mockPlatformRegistry,
|
|
Writer: mockWriter,
|
|
Input: input,
|
|
}
|
|
})
|
|
|
|
It("packages chaincodes", func() {
|
|
err := packager.Package()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(mockPlatformRegistry.NormalizePathCallCount()).To(Equal(1))
|
|
ccType, path := mockPlatformRegistry.NormalizePathArgsForCall(0)
|
|
Expect(ccType).To(Equal("TESTTYPE"))
|
|
Expect(path).To(Equal("testPath"))
|
|
|
|
Expect(mockPlatformRegistry.GetDeploymentPayloadCallCount()).To(Equal(1))
|
|
ccType, path = mockPlatformRegistry.GetDeploymentPayloadArgsForCall(0)
|
|
Expect(ccType).To(Equal("TESTTYPE"))
|
|
Expect(path).To(Equal("testPath"))
|
|
|
|
Expect(mockWriter.WriteFileCallCount()).To(Equal(1))
|
|
dir, name, pkgTarGzBytes := mockWriter.WriteFileArgsForCall(0)
|
|
wd, err := os.Getwd()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(dir).To(Equal(filepath.Join(wd, "testDir")))
|
|
Expect(name).To(Equal("testPackage"))
|
|
Expect(pkgTarGzBytes).NotTo(BeNil())
|
|
|
|
metadata, err := readMetadataFromBytes(pkgTarGzBytes)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(metadata).To(MatchJSON(`{"path":"normalizedPath","type":"testType","label":"testLabel"}`))
|
|
})
|
|
|
|
Context("when the path is not provided", func() {
|
|
BeforeEach(func() {
|
|
input.Path = ""
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("chaincode path must be specified"))
|
|
})
|
|
})
|
|
|
|
Context("when the type is not provided", func() {
|
|
BeforeEach(func() {
|
|
input.Type = ""
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("chaincode language must be specified"))
|
|
})
|
|
})
|
|
|
|
Context("when the output file is not provided", func() {
|
|
BeforeEach(func() {
|
|
input.OutputFile = ""
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("output file must be specified"))
|
|
})
|
|
})
|
|
|
|
Context("when the label is not provided", func() {
|
|
BeforeEach(func() {
|
|
input.Label = ""
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("package label must be specified"))
|
|
})
|
|
})
|
|
|
|
Context("when the label is invalid", func() {
|
|
BeforeEach(func() {
|
|
input.Label = "label with spaces"
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
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"))
|
|
})
|
|
})
|
|
|
|
Context("when the platform registry fails to normalize the path", func() {
|
|
BeforeEach(func() {
|
|
mockPlatformRegistry.NormalizePathReturns("", errors.New("cortado"))
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("failed to normalize chaincode path: cortado"))
|
|
})
|
|
})
|
|
|
|
Context("when the platform registry fails to get the deployment payload", func() {
|
|
BeforeEach(func() {
|
|
mockPlatformRegistry.GetDeploymentPayloadReturns(nil, errors.New("americano"))
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("error getting chaincode bytes: americano"))
|
|
})
|
|
})
|
|
|
|
Context("when writing the file fails", func() {
|
|
BeforeEach(func() {
|
|
mockWriter.WriteFileReturns(errors.New("espresso"))
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packager.Package()
|
|
Expect(err).To(MatchError("error writing chaincode package to testDir/testPackage: espresso"))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("PackageCmd", func() {
|
|
var packageCmd *cobra.Command
|
|
|
|
BeforeEach(func() {
|
|
packageCmd = chaincode.PackageCmd(nil)
|
|
packageCmd.SilenceErrors = true
|
|
packageCmd.SilenceUsage = true
|
|
packageCmd.SetArgs([]string{
|
|
"testPackage",
|
|
"--path=testPath",
|
|
"--lang=golang",
|
|
"--label=testLabel",
|
|
})
|
|
})
|
|
|
|
It("sets up the packager and attempts to package the chaincode", func() {
|
|
err := packageCmd.Execute()
|
|
Expect(err).To(MatchError(ContainSubstring("error getting chaincode bytes")))
|
|
})
|
|
|
|
Context("when more than one argument is provided", func() {
|
|
BeforeEach(func() {
|
|
packageCmd.SetArgs([]string{
|
|
"testPackage",
|
|
"whatthe",
|
|
})
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packageCmd.Execute()
|
|
Expect(err).To(MatchError("invalid number of args. expected only the output file"))
|
|
})
|
|
})
|
|
|
|
Context("when no argument is provided", func() {
|
|
BeforeEach(func() {
|
|
packageCmd.SetArgs([]string{})
|
|
})
|
|
|
|
It("returns an error", func() {
|
|
err := packageCmd.Execute()
|
|
Expect(err).To(MatchError("invalid number of args. expected only the output file"))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
func readMetadataFromBytes(pkgTarGzBytes []byte) ([]byte, error) {
|
|
buffer := bytes.NewBuffer(pkgTarGzBytes)
|
|
gzr, err := gzip.NewReader(buffer)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
defer gzr.Close()
|
|
tr := tar.NewReader(gzr)
|
|
for {
|
|
header, err := tr.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if header.Name == "metadata.json" {
|
|
return ioutil.ReadAll(tr)
|
|
}
|
|
}
|
|
return nil, errors.New("metadata.json not found")
|
|
}
|