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

     1  /*
     2  Copyright hechain. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package ccprovider
    18  
    19  import (
    20  	"archive/tar"
    21  	"bytes"
    22  	"compress/gzip"
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  	"testing"
    27  
    28  	"github.com/golang/protobuf/proto"
    29  	"github.com/hechain20/hechain/bccsp/sw"
    30  	"github.com/hyperledger/fabric-protos-go/peer"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func getDepSpec(name string, path string, version string, initArgs [][]byte) (*peer.ChaincodeDeploymentSpec, error) {
    35  	spec := &peer.ChaincodeSpec{Type: 1, ChaincodeId: &peer.ChaincodeID{Name: name, Path: path, Version: version}, Input: &peer.ChaincodeInput{Args: initArgs}}
    36  
    37  	codePackageBytes := bytes.NewBuffer(nil)
    38  	gz := gzip.NewWriter(codePackageBytes)
    39  	tw := tar.NewWriter(gz)
    40  
    41  	payload := []byte(name + path + version)
    42  	err := tw.WriteHeader(&tar.Header{
    43  		Name: "src/garbage.go",
    44  		Size: int64(len(payload)),
    45  		Mode: 0o100644,
    46  	})
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	_, err = tw.Write(payload)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	tw.Close()
    57  	gz.Close()
    58  
    59  	return &peer.ChaincodeDeploymentSpec{ChaincodeSpec: spec, CodePackage: codePackageBytes.Bytes()}, nil
    60  }
    61  
    62  func buildPackage(name string, path string, version string, initArgs [][]byte) (CCPackage, error) {
    63  	depSpec, err := getDepSpec(name, path, version, initArgs)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	buf, err := proto.Marshal(depSpec)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	cccdspack := &CDSPackage{GetHasher: cryptoProvider}
    78  	if _, err := cccdspack.InitFromBuffer(buf); err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	return cccdspack, nil
    83  }
    84  
    85  type mockCCInfoFSStorageMgrImpl struct {
    86  	CCMap map[string]CCPackage
    87  }
    88  
    89  func (m *mockCCInfoFSStorageMgrImpl) GetChaincode(ccNameVersion string) (CCPackage, error) {
    90  	return m.CCMap[ccNameVersion], nil
    91  }
    92  
    93  // here we test the cache implementation itself
    94  func TestCCInfoCache(t *testing.T) {
    95  	ccinfoFs := &mockCCInfoFSStorageMgrImpl{CCMap: map[string]CCPackage{}}
    96  	cccache := NewCCInfoCache(ccinfoFs)
    97  
    98  	// test the get side
    99  
   100  	// the cc data is not yet in the cache
   101  	_, err := cccache.GetChaincodeData("foo:1.0")
   102  	require.Error(t, err)
   103  
   104  	// put it in the file system
   105  	pack, err := buildPackage("foo", "mychaincode", "1.0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   106  	require.NoError(t, err)
   107  	ccinfoFs.CCMap["foo:1.0"] = pack
   108  
   109  	// expect it to be in the cache now
   110  	cd1, err := cccache.GetChaincodeData("foo:1.0")
   111  	require.NoError(t, err)
   112  
   113  	// it should still be in the cache
   114  	cd2, err := cccache.GetChaincodeData("foo:1.0")
   115  	require.NoError(t, err)
   116  
   117  	// they are not null
   118  	require.NotNil(t, cd1)
   119  	require.NotNil(t, cd2)
   120  
   121  	// put it in the file system
   122  	pack, err = buildPackage("foo", "mychaincode", "2.0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   123  	require.NoError(t, err)
   124  	ccinfoFs.CCMap["foo:2.0"] = pack
   125  
   126  	// create a dep spec to put
   127  	_, err = getDepSpec("foo", "mychaincode", "2.0", [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   128  	require.NoError(t, err)
   129  
   130  	// expect it to be cached
   131  	cd1, err = cccache.GetChaincodeData("foo:2.0")
   132  	require.NoError(t, err)
   133  
   134  	// it should still be in the cache
   135  	cd2, err = cccache.GetChaincodeData("foo:2.0")
   136  	require.NoError(t, err)
   137  
   138  	// they are not null
   139  	require.NotNil(t, cd1)
   140  	require.NotNil(t, cd2)
   141  }
   142  
   143  func TestPutChaincode(t *testing.T) {
   144  	ccname := ""
   145  	ccver := "1.0"
   146  	ccpath := "mychaincode"
   147  
   148  	ccinfoFs := &mockCCInfoFSStorageMgrImpl{CCMap: map[string]CCPackage{}}
   149  	NewCCInfoCache(ccinfoFs)
   150  
   151  	// Error case 1: ccname is empty
   152  	// create a dep spec to put
   153  	_, err := getDepSpec(ccname, ccpath, ccver, [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   154  	require.NoError(t, err)
   155  
   156  	// Error case 2: ccver is empty
   157  	ccname = "foo"
   158  	ccver = ""
   159  	_, err = getDepSpec(ccname, ccpath, ccver, [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   160  	require.NoError(t, err)
   161  
   162  	// Error case 3: ccfs.PutChainCode returns an error
   163  	ccinfoFs = &mockCCInfoFSStorageMgrImpl{CCMap: map[string]CCPackage{}}
   164  	NewCCInfoCache(ccinfoFs)
   165  
   166  	ccname = "foo"
   167  	ccver = "1.0"
   168  	_, err = getDepSpec(ccname, ccpath, ccver, [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   169  	require.NoError(t, err)
   170  }
   171  
   172  // here we test the peer's built-in cache after enabling it
   173  func TestCCInfoFSPeerInstance(t *testing.T) {
   174  	ccname := "bar"
   175  	ccver := "1.0"
   176  	ccpath := "mychaincode"
   177  
   178  	// the cc data is not yet in the cache
   179  	_, err := GetChaincodeFromFS("bar:1.0")
   180  	require.Error(t, err)
   181  
   182  	// create a dep spec to put
   183  	ds, err := getDepSpec(ccname, ccpath, ccver, [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")})
   184  	require.NoError(t, err)
   185  
   186  	// put it
   187  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   188  	require.NoError(t, err)
   189  	ccinfoFSImpl := &CCInfoFSImpl{GetHasher: cryptoProvider}
   190  	_, err = ccinfoFSImpl.PutChaincode(ds)
   191  	require.NoError(t, err)
   192  
   193  	// Get all installed chaincodes, it should not return 0 chaincodes
   194  	resp, err := GetInstalledChaincodes()
   195  	require.NoError(t, err)
   196  	require.NotNil(t, resp)
   197  	require.NotZero(t, len(resp.Chaincodes), "GetInstalledChaincodes should not have returned 0 chaincodes")
   198  
   199  	// get chaincode data
   200  	_, err = GetChaincodeData("bar:1.0")
   201  	require.NoError(t, err)
   202  }
   203  
   204  func TestGetInstalledChaincodesErrorPaths(t *testing.T) {
   205  	// Get the existing chaincode install path value and set it
   206  	// back after we are done with the test
   207  	cip := chaincodeInstallPath
   208  	defer SetChaincodesPath(cip)
   209  
   210  	// Create a temp dir and remove it at the end
   211  	dir, err := ioutil.TempDir(os.TempDir(), "chaincodes")
   212  	require.NoError(t, err)
   213  	defer os.RemoveAll(dir)
   214  
   215  	// Set the above created directory as the chaincode install path
   216  	SetChaincodesPath(dir)
   217  	err = ioutil.WriteFile(filepath.Join(dir, "idontexist.1.0"), []byte("test"), 0o777)
   218  	require.NoError(t, err)
   219  	resp, err := GetInstalledChaincodes()
   220  	require.NoError(t, err)
   221  	require.Equal(t, 0, len(resp.Chaincodes),
   222  		"Expected 0 chaincodes but GetInstalledChaincodes returned %s chaincodes", len(resp.Chaincodes))
   223  }
   224  
   225  func TestChaincodePackageExists(t *testing.T) {
   226  	_, err := ChaincodePackageExists("foo1", "1.0")
   227  	require.Error(t, err)
   228  }
   229  
   230  func TestSetChaincodesPath(t *testing.T) {
   231  	dir, err := ioutil.TempDir(os.TempDir(), "setchaincodes")
   232  	if err != nil {
   233  		require.Fail(t, err.Error(), "Unable to create temp dir")
   234  	}
   235  	defer os.RemoveAll(dir)
   236  	t.Logf("created temp dir %s", dir)
   237  
   238  	// Get the existing chaincode install path value and set it
   239  	// back after we are done with the test
   240  	cip := chaincodeInstallPath
   241  	defer SetChaincodesPath(cip)
   242  
   243  	f, err := ioutil.TempFile(dir, "chaincodes")
   244  	require.NoError(t, err)
   245  	require.Panics(t, func() {
   246  		SetChaincodesPath(f.Name())
   247  	}, "SetChaincodesPath should have paniced if a file is passed to it")
   248  
   249  	// Following code works on mac but does not work in CI
   250  	// // Make the directory read only
   251  	// err = os.Chmod(dir, 0444)
   252  	// assert.NoError(t, err)
   253  	// cdir := filepath.Join(dir, "chaincodesdir")
   254  	// assert.Panics(t, func() {
   255  	// 	SetChaincodesPath(cdir)
   256  	// }, "SetChaincodesPath should have paniced if it is not able to stat the dir")
   257  
   258  	// // Make the directory read and execute
   259  	// err = os.Chmod(dir, 0555)
   260  	// assert.NoError(t, err)
   261  	// assert.Panics(t, func() {
   262  	// 	SetChaincodesPath(cdir)
   263  	// }, "SetChaincodesPath should have paniced if it is not able to create the dir")
   264  }
   265  
   266  var ccinfocachetestpath = "/tmp/ccinfocachetest"
   267  
   268  func TestMain(m *testing.M) {
   269  	os.RemoveAll(ccinfocachetestpath)
   270  
   271  	SetChaincodesPath(ccinfocachetestpath)
   272  	rc := m.Run()
   273  	os.RemoveAll(ccinfocachetestpath)
   274  	os.Exit(rc)
   275  }