github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/common/ccprovider/ccprovider_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package ccprovider_test
     8  
     9  import (
    10  	"crypto/sha256"
    11  	"io/ioutil"
    12  	"os"
    13  	"path"
    14  	"path/filepath"
    15  	"strings"
    16  	"testing"
    17  
    18  	"github.com/golang/protobuf/proto"
    19  	"github.com/hechain20/hechain/bccsp/sw"
    20  	"github.com/hechain20/hechain/common/chaincode"
    21  	"github.com/hechain20/hechain/core/common/ccprovider"
    22  	"github.com/hyperledger/fabric-protos-go/peer"
    23  	"github.com/pkg/errors"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  func TestInstalledCCs(t *testing.T) {
    28  	tmpDir, hashes := setupDirectoryStructure(t)
    29  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    30  	require.NoError(t, err)
    31  
    32  	defer func() {
    33  		os.RemoveAll(tmpDir)
    34  	}()
    35  
    36  	testCases := []struct {
    37  		name              string
    38  		directory         string
    39  		expected          []chaincode.InstalledChaincode
    40  		errorContains     string
    41  		ls                ccprovider.DirEnumerator
    42  		extractCCFromPath ccprovider.ChaincodeExtractor
    43  	}{
    44  		{
    45  			name:              "Non-empty directory",
    46  			ls:                ioutil.ReadDir,
    47  			extractCCFromPath: ccprovider.LoadPackage,
    48  			expected: []chaincode.InstalledChaincode{
    49  				{
    50  					Name:    "example02",
    51  					Version: "1.0",
    52  					Hash:    hashes["example02.1.0"],
    53  				},
    54  				{
    55  					Name:    "example04",
    56  					Version: "1",
    57  					Hash:    hashes["example04.1"],
    58  				},
    59  			},
    60  			directory: "nonempty",
    61  		},
    62  		{
    63  			name:              "Nonexistent directory",
    64  			ls:                ioutil.ReadDir,
    65  			extractCCFromPath: ccprovider.LoadPackage,
    66  			expected:          nil,
    67  			directory:         "nonexistent",
    68  		},
    69  		{
    70  			name:              "Empty directory",
    71  			ls:                ioutil.ReadDir,
    72  			extractCCFromPath: ccprovider.LoadPackage,
    73  			expected:          nil,
    74  			directory:         "empty",
    75  		},
    76  		{
    77  			name: "No permission to open directory",
    78  			ls: func(_ string) ([]os.FileInfo, error) {
    79  				return nil, errors.New("orange")
    80  			},
    81  			extractCCFromPath: ccprovider.LoadPackage,
    82  			expected:          nil,
    83  			directory:         "nopermission",
    84  			errorContains:     "orange",
    85  		},
    86  		{
    87  			name: "No permission on chaincode files",
    88  			ls:   ioutil.ReadDir,
    89  			extractCCFromPath: func(_ string, _ string, _ ccprovider.GetHasher) (ccprovider.CCPackage, error) {
    90  				return nil, errors.New("banana")
    91  			},
    92  			expected:      nil,
    93  			directory:     "nopermissionforfiles",
    94  			errorContains: "banana",
    95  		},
    96  	}
    97  	_ = testCases
    98  
    99  	for _, test := range testCases {
   100  		test := test
   101  		t.Run(test.name, func(t *testing.T) {
   102  			c := &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider}
   103  			res, err := c.ListInstalledChaincodes(path.Join(tmpDir, test.directory), test.ls, test.extractCCFromPath)
   104  			require.Equal(t, test.expected, res)
   105  			if test.errorContains == "" {
   106  				require.NoError(t, err)
   107  			} else {
   108  				require.Contains(t, err.Error(), test.errorContains)
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestSetGetChaincodeInstallPath(t *testing.T) {
   115  	tempDir, err := ioutil.TempDir("", "ccprovider")
   116  	require.NoError(t, err)
   117  	defer os.RemoveAll(tempDir)
   118  
   119  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   120  	require.NoError(t, err)
   121  	c := &ccprovider.CCInfoFSImpl{GetHasher: cryptoProvider}
   122  	installPath := c.GetChaincodeInstallPath()
   123  	defer ccprovider.SetChaincodesPath(installPath)
   124  
   125  	path := filepath.Join(tempDir, "blahblah")
   126  	ccprovider.SetChaincodesPath(path)
   127  	require.DirExistsf(t, path, "expect %s to be created")
   128  
   129  	require.Equal(t, path, c.GetChaincodeInstallPath())
   130  }
   131  
   132  func setupDirectoryStructure(t *testing.T) (string, map[string][]byte) {
   133  	files := []string{
   134  		"example02.1.0", // Version contains the delimiter '.' is a valid case
   135  		"example03",     // No version specified
   136  		"example04.1",   // Version doesn't contain the '.' delimiter
   137  	}
   138  	hashes := map[string][]byte{}
   139  	tmp, err := ioutil.TempDir("", "test-installed-cc")
   140  	require.NoError(t, err)
   141  	dir := path.Join(tmp, "empty")
   142  	require.NoError(t, os.Mkdir(dir, 0o755))
   143  	dir = path.Join(tmp, "nonempty")
   144  	require.NoError(t, os.Mkdir(dir, 0o755))
   145  	dir = path.Join(tmp, "nopermission")
   146  	require.NoError(t, os.Mkdir(dir, 0o755))
   147  	dir = path.Join(tmp, "nopermissionforfiles")
   148  	require.NoError(t, os.Mkdir(dir, 0o755))
   149  	noPermissionFile := path.Join(tmp, "nopermissionforfiles", "nopermission.1")
   150  	_, err = os.Create(noPermissionFile)
   151  	require.NoError(t, err)
   152  	dir = path.Join(tmp, "nonempty")
   153  	require.NoError(t, os.Mkdir(path.Join(tmp, "nonempty", "directory"), 0o755))
   154  	for _, f := range files {
   155  		var name, ver string
   156  		parts := strings.SplitN(f, ".", 2)
   157  		name = parts[0]
   158  		if len(parts) > 1 {
   159  			ver = parts[1]
   160  		}
   161  		file, err := os.Create(path.Join(dir, f))
   162  		require.NoError(t, err)
   163  		cds := &peer.ChaincodeDeploymentSpec{
   164  			ChaincodeSpec: &peer.ChaincodeSpec{
   165  				ChaincodeId: &peer.ChaincodeID{Name: name, Version: ver},
   166  			},
   167  		}
   168  
   169  		codehash := sha256.New()
   170  		codehash.Write(cds.CodePackage)
   171  
   172  		metahash := sha256.New()
   173  		metahash.Write([]byte(name))
   174  		metahash.Write([]byte(ver))
   175  
   176  		hash := sha256.New()
   177  		hash.Write(codehash.Sum(nil))
   178  		hash.Write(metahash.Sum(nil))
   179  
   180  		hashes[f] = hash.Sum(nil)
   181  
   182  		b, _ := proto.Marshal(cds)
   183  		file.Write(b)
   184  		file.Close()
   185  	}
   186  
   187  	return tmp, hashes
   188  }