github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/scc/qscc/query_test.go (about)

     1  /*
     2  Copyright hechain. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package qscc
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"testing"
    14  
    15  	"github.com/hechain20/hechain/bccsp/sw"
    16  	"github.com/hechain20/hechain/common/ledger/testutil"
    17  	"github.com/hechain20/hechain/common/util"
    18  	"github.com/hechain20/hechain/core/aclmgmt/mocks"
    19  	"github.com/hechain20/hechain/core/aclmgmt/resources"
    20  	ledger2 "github.com/hechain20/hechain/core/ledger"
    21  	"github.com/hechain20/hechain/core/ledger/ledgermgmt"
    22  	"github.com/hechain20/hechain/core/ledger/ledgermgmt/ledgermgmttest"
    23  	"github.com/hechain20/hechain/core/peer"
    24  	"github.com/hechain20/hechain/protoutil"
    25  	"github.com/hyperledger/fabric-chaincode-go/shim"
    26  	"github.com/hyperledger/fabric-chaincode-go/shimtest"
    27  	"github.com/hyperledger/fabric-protos-go/common"
    28  	peer2 "github.com/hyperledger/fabric-protos-go/peer"
    29  	"github.com/pkg/errors"
    30  	"github.com/spf13/viper"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func setupTestLedger(chainid string, path string) (*shimtest.MockStub, *peer.Peer, func(), error) {
    35  	mockAclProvider.Reset()
    36  
    37  	viper.Set("peer.fileSystemPath", path)
    38  	testDir, err := ioutil.TempDir("", "qscc_test")
    39  	if err != nil {
    40  		return nil, nil, nil, err
    41  	}
    42  
    43  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    44  	if err != nil {
    45  		return nil, nil, nil, err
    46  	}
    47  
    48  	initializer := ledgermgmttest.NewInitializer(testDir)
    49  
    50  	ledgerMgr := ledgermgmt.NewLedgerMgr(initializer)
    51  
    52  	cleanup := func() {
    53  		ledgerMgr.Close()
    54  		os.RemoveAll(testDir)
    55  	}
    56  	peerInstance := &peer.Peer{
    57  		LedgerMgr:      ledgerMgr,
    58  		CryptoProvider: cryptoProvider,
    59  	}
    60  	peer.CreateMockChannel(peerInstance, chainid, nil)
    61  
    62  	lq := &LedgerQuerier{
    63  		aclProvider: mockAclProvider,
    64  		ledgers:     peerInstance,
    65  	}
    66  	stub := shimtest.NewMockStub("LedgerQuerier", lq)
    67  	if res := stub.MockInit("1", nil); res.Status != shim.OK {
    68  		return nil, peerInstance, cleanup, fmt.Errorf("Init failed for test ledger [%s] with message: %s", chainid, string(res.Message))
    69  	}
    70  	return stub, peerInstance, cleanup, nil
    71  }
    72  
    73  // pass the prop so we can conveniently inline it in the call and get it back
    74  func resetProvider(res, chainid string, prop *peer2.SignedProposal, retErr error) *peer2.SignedProposal {
    75  	if prop == nil {
    76  		prop, _ = protoutil.MockSignedEndorserProposalOrPanic(
    77  			chainid,
    78  			&peer2.ChaincodeSpec{
    79  				ChaincodeId: &peer2.ChaincodeID{
    80  					Name: "qscc",
    81  				},
    82  			},
    83  			[]byte("Alice"),
    84  			[]byte("msg1"),
    85  		)
    86  	}
    87  	mockAclProvider.Reset()
    88  	mockAclProvider.On("CheckACL", res, chainid, prop).Return(retErr)
    89  	return prop
    90  }
    91  
    92  func tempDir(t *testing.T, stem string) string {
    93  	path, err := ioutil.TempDir("", "qscc-"+stem)
    94  	require.NoError(t, err)
    95  	return path
    96  }
    97  
    98  func TestQueryGetChainInfo(t *testing.T) {
    99  	chainid := "mytestchainid1"
   100  	path := tempDir(t, "test1")
   101  	defer os.RemoveAll(path)
   102  
   103  	stub, _, cleanup, err := setupTestLedger(chainid, path)
   104  	if err != nil {
   105  		t.Fatalf(err.Error())
   106  	}
   107  	defer cleanup()
   108  
   109  	args := [][]byte{[]byte(GetChainInfo), []byte(chainid)}
   110  	prop := resetProvider(resources.Qscc_GetChainInfo, chainid, nil, nil)
   111  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   112  	require.Equal(t, int32(shim.OK), res.Status, "GetChainInfo failed with err: %s", res.Message)
   113  
   114  	args = [][]byte{[]byte(GetChainInfo)}
   115  	res = stub.MockInvoke("2", args)
   116  	require.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo should have failed because no channel id was provided")
   117  
   118  	args = [][]byte{[]byte(GetChainInfo), []byte("fakechainid")}
   119  	res = stub.MockInvoke("3", args)
   120  	require.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo should have failed because the channel id does not exist")
   121  }
   122  
   123  func TestQueryGetTransactionByID(t *testing.T) {
   124  	chainid := "mytestchainid2"
   125  	path := tempDir(t, "test2")
   126  	defer os.RemoveAll(path)
   127  
   128  	stub, _, cleanup, err := setupTestLedger(chainid, path)
   129  	if err != nil {
   130  		t.Fatalf(err.Error())
   131  	}
   132  	defer cleanup()
   133  
   134  	args := [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte("1")}
   135  	prop := resetProvider(resources.Qscc_GetTransactionByID, chainid, &peer2.SignedProposal{}, nil)
   136  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   137  	require.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed with invalid txid: 1")
   138  
   139  	args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte(nil)}
   140  	res = stub.MockInvoke("2", args)
   141  	require.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed with invalid txid: nil")
   142  
   143  	// Test with wrong number of parameters
   144  	args = [][]byte{[]byte(GetTransactionByID), []byte(chainid)}
   145  	res = stub.MockInvoke("3", args)
   146  	require.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed due to incorrect number of arguments")
   147  }
   148  
   149  func TestQueryGetBlockByNumber(t *testing.T) {
   150  	chainid := "mytestchainid3"
   151  	path := tempDir(t, "test3")
   152  	defer os.RemoveAll(path)
   153  
   154  	stub, _, cleanup, err := setupTestLedger(chainid, path)
   155  	if err != nil {
   156  		t.Fatalf(err.Error())
   157  	}
   158  	defer cleanup()
   159  
   160  	// block number 0 (genesis block) would already be present in the ledger
   161  	args := [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("0")}
   162  	prop := resetProvider(resources.Qscc_GetBlockByNumber, chainid, nil, nil)
   163  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   164  	require.Equal(t, int32(shim.OK), res.Status, "GetBlockByNumber should have succeeded for block number: 0")
   165  
   166  	// block number 1 should not be present in the ledger
   167  	args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
   168  	res = stub.MockInvoke("2", args)
   169  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber should have failed with invalid number: 1")
   170  
   171  	// block number cannot be nil
   172  	args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte(nil)}
   173  	res = stub.MockInvoke("3", args)
   174  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber should have failed with nil block number")
   175  }
   176  
   177  func TestQueryGetBlockByHash(t *testing.T) {
   178  	chainid := "mytestchainid4"
   179  	path := tempDir(t, "test4")
   180  	defer os.RemoveAll(path)
   181  
   182  	stub, _, cleanup, err := setupTestLedger(chainid, path)
   183  	if err != nil {
   184  		t.Fatalf(err.Error())
   185  	}
   186  	defer cleanup()
   187  
   188  	args := [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte("0")}
   189  	prop := resetProvider(resources.Qscc_GetBlockByHash, chainid, &peer2.SignedProposal{}, nil)
   190  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   191  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash should have failed with invalid hash: 0")
   192  
   193  	args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte(nil)}
   194  	res = stub.MockInvoke("2", args)
   195  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash should have failed with nil hash")
   196  }
   197  
   198  func TestQueryGetBlockByTxID(t *testing.T) {
   199  	chainid := "mytestchainid5"
   200  	path := tempDir(t, "test5")
   201  	defer os.RemoveAll(path)
   202  
   203  	stub, _, cleanup, err := setupTestLedger(chainid, path)
   204  	if err != nil {
   205  		t.Fatalf(err.Error())
   206  	}
   207  	defer cleanup()
   208  
   209  	args := [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte("")}
   210  	prop := resetProvider(resources.Qscc_GetBlockByTxID, chainid, &peer2.SignedProposal{}, nil)
   211  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   212  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByTxID should have failed with blank txId.")
   213  }
   214  
   215  func TestFailingCC2CC(t *testing.T) {
   216  	t.Run("BadProposal", func(t *testing.T) {
   217  		stub := shimtest.NewMockStub("testchannel", &LedgerQuerier{})
   218  		args := [][]byte{[]byte("funcname"), []byte("testchannel")}
   219  		sProp := &peer2.SignedProposal{
   220  			ProposalBytes: []byte("garbage"),
   221  		}
   222  		sProp.Signature = sProp.ProposalBytes
   223  		// Set the ACLProvider to have a failure
   224  		resetProvider(resources.Qscc_GetChainInfo, "testchannel", sProp, nil)
   225  		res := stub.MockInvokeWithSignedProposal("2", args, sProp)
   226  		require.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo must fail: %s", res.Message)
   227  		require.Contains(t, res.Message, "Failed to identify the called chaincode: could not unmarshal proposal: proto: can't skip unknown wire type 7")
   228  	})
   229  
   230  	t.Run("DifferentInvokedCC", func(t *testing.T) {
   231  		stub := shimtest.NewMockStub("testchannel", &LedgerQuerier{})
   232  		args := [][]byte{[]byte("funcname"), []byte("testchannel")}
   233  		sProp, _ := protoutil.MockSignedEndorserProposalOrPanic(
   234  			"testchannel",
   235  			&peer2.ChaincodeSpec{
   236  				ChaincodeId: &peer2.ChaincodeID{
   237  					Name: "usercc",
   238  				},
   239  			},
   240  			[]byte("Alice"),
   241  			[]byte("msg1"),
   242  		)
   243  		sProp.Signature = sProp.ProposalBytes
   244  		// Set the ACLProvider to have a failure
   245  		resetProvider(resources.Qscc_GetChainInfo, "testchannel", sProp, nil)
   246  		res := stub.MockInvokeWithSignedProposal("2", args, sProp)
   247  		require.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo must fail: %s", res.Message)
   248  		require.Contains(t, res.Message, "Rejecting invoke of QSCC from another chaincode because of potential for deadlocks, original invocation for 'usercc'")
   249  	})
   250  }
   251  
   252  func TestFailingAccessControl(t *testing.T) {
   253  	chainid := "mytestchainid6"
   254  	path := tempDir(t, "test6")
   255  	defer os.RemoveAll(path)
   256  
   257  	_, p, cleanup, err := setupTestLedger(chainid, path)
   258  	if err != nil {
   259  		t.Fatalf(err.Error())
   260  	}
   261  	defer cleanup()
   262  	e := &LedgerQuerier{
   263  		aclProvider: mockAclProvider,
   264  		ledgers:     p,
   265  	}
   266  	stub := shimtest.NewMockStub("LedgerQuerier", e)
   267  
   268  	// GetChainInfo
   269  	args := [][]byte{[]byte(GetChainInfo), []byte(chainid)}
   270  	sProp, _ := protoutil.MockSignedEndorserProposalOrPanic(chainid,
   271  		&peer2.ChaincodeSpec{
   272  			ChaincodeId: &peer2.ChaincodeID{
   273  				Name: "qscc",
   274  			},
   275  		},
   276  		[]byte("Alice"),
   277  		[]byte("msg1"),
   278  	)
   279  	sProp.Signature = sProp.ProposalBytes
   280  	// Set the ACLProvider to have a failure
   281  	resetProvider(resources.Qscc_GetChainInfo, chainid, sProp, errors.New("Failed access control"))
   282  	res := stub.MockInvokeWithSignedProposal("2", args, sProp)
   283  	require.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo must fail: %s", res.Message)
   284  	require.Contains(t, res.Message, "Failed access control")
   285  	// assert that the expectations were met
   286  	mockAclProvider.AssertExpectations(t)
   287  
   288  	// GetBlockByNumber
   289  	args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
   290  	sProp, _ = protoutil.MockSignedEndorserProposalOrPanic(
   291  		chainid,
   292  		&peer2.ChaincodeSpec{
   293  			ChaincodeId: &peer2.ChaincodeID{
   294  				Name: "qscc",
   295  			},
   296  		},
   297  		[]byte("Alice"),
   298  		[]byte("msg1"),
   299  	)
   300  	sProp.Signature = sProp.ProposalBytes
   301  	// Set the ACLProvider to have a failure
   302  	resetProvider(resources.Qscc_GetBlockByNumber, chainid, sProp, errors.New("Failed access control"))
   303  	res = stub.MockInvokeWithSignedProposal("2", args, sProp)
   304  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber must fail: %s", res.Message)
   305  	require.Contains(t, res.Message, "Failed access control")
   306  	// assert that the expectations were met
   307  	mockAclProvider.AssertExpectations(t)
   308  
   309  	// GetBlockByHash
   310  	args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte("1")}
   311  	sProp, _ = protoutil.MockSignedEndorserProposalOrPanic(
   312  		chainid,
   313  		&peer2.ChaincodeSpec{
   314  			ChaincodeId: &peer2.ChaincodeID{
   315  				Name: "qscc",
   316  			},
   317  		},
   318  		[]byte("Alice"),
   319  		[]byte("msg1"),
   320  	)
   321  	sProp.Signature = sProp.ProposalBytes
   322  	// Set the ACLProvider to have a failure
   323  	resetProvider(resources.Qscc_GetBlockByHash, chainid, sProp, errors.New("Failed access control"))
   324  	res = stub.MockInvokeWithSignedProposal("2", args, sProp)
   325  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash must fail: %s", res.Message)
   326  	require.Contains(t, res.Message, "Failed access control")
   327  	// assert that the expectations were met
   328  	mockAclProvider.AssertExpectations(t)
   329  
   330  	// GetBlockByTxID
   331  	args = [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte("1")}
   332  	sProp, _ = protoutil.MockSignedEndorserProposalOrPanic(
   333  		chainid,
   334  		&peer2.ChaincodeSpec{
   335  			ChaincodeId: &peer2.ChaincodeID{
   336  				Name: "qscc",
   337  			},
   338  		},
   339  		[]byte("Alice"),
   340  		[]byte("msg1"),
   341  	)
   342  	sProp.Signature = sProp.ProposalBytes
   343  	// Set the ACLProvider to have a failure
   344  	resetProvider(resources.Qscc_GetBlockByTxID, chainid, sProp, errors.New("Failed access control"))
   345  	res = stub.MockInvokeWithSignedProposal("2", args, sProp)
   346  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByTxID must fail: %s", res.Message)
   347  	require.Contains(t, res.Message, "Failed access control")
   348  	// assert that the expectations were met
   349  	mockAclProvider.AssertExpectations(t)
   350  
   351  	// GetTransactionByID
   352  	args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte("1")}
   353  	sProp, _ = protoutil.MockSignedEndorserProposalOrPanic(
   354  		chainid,
   355  		&peer2.ChaincodeSpec{
   356  			ChaincodeId: &peer2.ChaincodeID{
   357  				Name: "qscc",
   358  			},
   359  		},
   360  		[]byte("Alice"),
   361  		[]byte("msg1"),
   362  	)
   363  	sProp.Signature = sProp.ProposalBytes
   364  	// Set the ACLProvider to have a failure
   365  	resetProvider(resources.Qscc_GetTransactionByID, chainid, sProp, errors.New("Failed access control"))
   366  	res = stub.MockInvokeWithSignedProposal("2", args, sProp)
   367  	require.Equal(t, int32(shim.ERROR), res.Status, "Qscc_GetTransactionByID must fail: %s", res.Message)
   368  	require.Contains(t, res.Message, "Failed access control")
   369  	// assert that the expectations were met
   370  	mockAclProvider.AssertExpectations(t)
   371  }
   372  
   373  func TestQueryNonexistentFunction(t *testing.T) {
   374  	chainid := "mytestchainid7"
   375  	path := tempDir(t, "test7")
   376  	defer os.RemoveAll(path)
   377  
   378  	stub, _, cleanup, err := setupTestLedger(chainid, path)
   379  	if err != nil {
   380  		t.Fatalf(err.Error())
   381  	}
   382  	defer cleanup()
   383  
   384  	args := [][]byte{[]byte("GetBlocks"), []byte(chainid), []byte("arg1")}
   385  	prop := resetProvider("qscc/GetBlocks", chainid, &peer2.SignedProposal{}, nil)
   386  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   387  	require.Equal(t, int32(shim.ERROR), res.Status, "GetBlocks should have failed because the function does not exist")
   388  }
   389  
   390  // TestQueryGeneratedBlock tests various queries for a newly generated block
   391  // that contains two transactions
   392  func TestQueryGeneratedBlock(t *testing.T) {
   393  	chainid := "mytestchainid8"
   394  	path := tempDir(t, "test8")
   395  	defer os.RemoveAll(path)
   396  
   397  	stub, p, cleanup, err := setupTestLedger(chainid, path)
   398  	if err != nil {
   399  		t.Fatalf(err.Error())
   400  	}
   401  	defer cleanup()
   402  
   403  	block1 := addBlockForTesting(t, chainid, p)
   404  
   405  	// block number 1 should now exist
   406  	args := [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
   407  	prop := resetProvider(resources.Qscc_GetBlockByNumber, chainid, nil, nil)
   408  	res := stub.MockInvokeWithSignedProposal("1", args, prop)
   409  	require.Equal(t, int32(shim.OK), res.Status, "GetBlockByNumber should have succeeded for block number 1")
   410  
   411  	// block number 1
   412  	args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), protoutil.BlockHeaderHash(block1.Header)}
   413  	prop = resetProvider(resources.Qscc_GetBlockByHash, chainid, nil, nil)
   414  	res = stub.MockInvokeWithSignedProposal("2", args, prop)
   415  	require.Equal(t, int32(shim.OK), res.Status, "GetBlockByHash should have succeeded for block 1 hash")
   416  
   417  	// drill into the block to find the transaction ids it contains
   418  	for _, d := range block1.Data.Data {
   419  		ebytes := d
   420  		if ebytes != nil {
   421  			if env, err := protoutil.GetEnvelopeFromBlock(ebytes); err != nil {
   422  				t.Fatalf("error getting envelope from block: %s", err)
   423  			} else if env != nil {
   424  				payload, err := protoutil.UnmarshalPayload(env.Payload)
   425  				if err != nil {
   426  					t.Fatalf("error extracting payload from envelope: %s", err)
   427  				}
   428  				chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   429  				if err != nil {
   430  					t.Fatalf(err.Error())
   431  				}
   432  				if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION {
   433  					args = [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte(chdr.TxId)}
   434  					mockAclProvider.Reset()
   435  					prop = resetProvider(resources.Qscc_GetBlockByTxID, chainid, nil, nil)
   436  					res = stub.MockInvokeWithSignedProposal("3", args, prop)
   437  					require.Equal(t, int32(shim.OK), res.Status, "GetBlockByTxId should have succeeded for txid: %s", chdr.TxId)
   438  
   439  					args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte(chdr.TxId)}
   440  					prop = resetProvider(resources.Qscc_GetTransactionByID, chainid, nil, nil)
   441  					res = stub.MockInvokeWithSignedProposal("4", args, prop)
   442  					require.Equal(t, int32(shim.OK), res.Status, "GetTransactionById should have succeeded for txid: %s", chdr.TxId)
   443  				}
   444  			}
   445  		}
   446  	}
   447  }
   448  
   449  func addBlockForTesting(t *testing.T, chainid string, p *peer.Peer) *common.Block {
   450  	ledger := p.GetLedger(chainid)
   451  	defer ledger.Close()
   452  
   453  	txid1 := util.GenerateUUID()
   454  	simulator, _ := ledger.NewTxSimulator(txid1)
   455  	simulator.SetState("ns1", "key1", []byte("value1"))
   456  	simulator.SetState("ns1", "key2", []byte("value2"))
   457  	simulator.SetState("ns1", "key3", []byte("value3"))
   458  	simulator.Done()
   459  	simRes1, _ := simulator.GetTxSimulationResults()
   460  	pubSimResBytes1, _ := simRes1.GetPubSimulationBytes()
   461  
   462  	txid2 := util.GenerateUUID()
   463  	simulator, _ = ledger.NewTxSimulator(txid2)
   464  	simulator.SetState("ns2", "key4", []byte("value4"))
   465  	simulator.SetState("ns2", "key5", []byte("value5"))
   466  	simulator.SetState("ns2", "key6", []byte("value6"))
   467  	simulator.Done()
   468  	simRes2, _ := simulator.GetTxSimulationResults()
   469  	pubSimResBytes2, _ := simRes2.GetPubSimulationBytes()
   470  
   471  	bcInfo, err := ledger.GetBlockchainInfo()
   472  	require.NoError(t, err)
   473  	block1 := testutil.ConstructBlock(t, 1, bcInfo.CurrentBlockHash, [][]byte{pubSimResBytes1, pubSimResBytes2}, false)
   474  	ledger.CommitLegacy(&ledger2.BlockAndPvtData{Block: block1}, &ledger2.CommitOptions{})
   475  	return block1
   476  }
   477  
   478  var mockAclProvider *mocks.MockACLProvider
   479  
   480  func TestMain(m *testing.M) {
   481  	mockAclProvider = &mocks.MockACLProvider{}
   482  	mockAclProvider.Reset()
   483  
   484  	os.Exit(m.Run())
   485  }