github.com/defanghe/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/state_listener_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lockbasedtxmgr
     8  
     9  import (
    10  	"testing"
    11  
    12  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    13  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    14  	"github.com/hyperledger/fabric/common/ledger/testutil"
    15  	"github.com/hyperledger/fabric/core/ledger"
    16  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate"
    17  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
    18  	"github.com/hyperledger/fabric/core/ledger/mock"
    19  	"github.com/hyperledger/fabric/core/ledger/util"
    20  	"github.com/hyperledger/fabric/protoutil"
    21  	"github.com/stretchr/testify/assert"
    22  )
    23  
    24  func TestStateListener(t *testing.T) {
    25  	testLedgerid := "testLedger"
    26  	ml1 := new(mock.StateListener)
    27  	ml1.InterestedInNamespacesStub = func() []string { return []string{"ns1", "ns2"} }
    28  
    29  	ml2 := new(mock.StateListener)
    30  	ml2.InterestedInNamespacesStub = func() []string { return []string{"ns2", "ns3"} }
    31  
    32  	ml3 := new(mock.StateListener)
    33  	ml3.InterestedInNamespacesStub = func() []string { return []string{"ns4"} }
    34  
    35  	testEnv := testEnvsMap[levelDBtestEnvName]
    36  	testEnv.init(t, testLedgerid, nil)
    37  	defer testEnv.cleanup()
    38  	txmgr := testEnv.getTxMgr().(*LockBasedTxMgr)
    39  	txmgr.stateListeners = []ledger.StateListener{ml1, ml2, ml3}
    40  
    41  	// Mimic commit of block 1 with updates in namespaces ns1, ns2, and ns3
    42  	// This should cause callback to ml1 and ml2 but not to ml3
    43  	sampleBatch := privacyenabledstate.NewUpdateBatch()
    44  	sampleBatch.PubUpdates.Put("ns1", "key1_1", []byte("value1_1"), version.NewHeight(1, 1))
    45  	sampleBatch.PubUpdates.Put("ns1", "key1_2", []byte("value1_2"), version.NewHeight(1, 2))
    46  	sampleBatch.PubUpdates.Put("ns2", "key2_1", []byte("value2_1"), version.NewHeight(1, 3))
    47  	sampleBatch.PubUpdates.Put("ns3", "key3_1", []byte("value3_1"), version.NewHeight(1, 4))
    48  	dummyBlock := protoutil.NewBlock(1, []byte("dummyHash"))
    49  	txmgr.current = &current{block: dummyBlock, batch: sampleBatch}
    50  	txmgr.invokeNamespaceListeners()
    51  	assert.Equal(t, 1, ml1.HandleStateUpdatesCallCount())
    52  	assert.Equal(t, 1, ml2.HandleStateUpdatesCallCount())
    53  	assert.Equal(t, 0, ml3.HandleStateUpdatesCallCount())
    54  	expectedLedgerid, expectedStateUpdate, expectedHt :=
    55  		testLedgerid,
    56  		ledger.StateUpdates{
    57  			"ns1": &ledger.KVStateUpdates{
    58  				PublicUpdates: []*kvrwset.KVWrite{
    59  					{Key: "key1_1", Value: []byte("value1_1")},
    60  					{Key: "key1_2", Value: []byte("value1_2")},
    61  				},
    62  			},
    63  			"ns2": &ledger.KVStateUpdates{
    64  				PublicUpdates: []*kvrwset.KVWrite{
    65  					{Key: "key2_1", Value: []byte("value2_1")},
    66  				},
    67  			},
    68  		},
    69  		uint64(1)
    70  	checkHandleStateUpdatesCallback(t, ml1, 0, expectedLedgerid, expectedStateUpdate, expectedHt)
    71  	expectedLedgerid, expectedStateUpdate, expectedHt =
    72  		testLedgerid,
    73  		ledger.StateUpdates{
    74  			"ns2": &ledger.KVStateUpdates{
    75  				PublicUpdates: []*kvrwset.KVWrite{
    76  					{Key: "key2_1", Value: []byte("value2_1")},
    77  				},
    78  			},
    79  			"ns3": &ledger.KVStateUpdates{
    80  				PublicUpdates: []*kvrwset.KVWrite{
    81  					{Key: "key3_1", Value: []byte("value3_1")},
    82  				},
    83  			},
    84  		},
    85  		uint64(1)
    86  	checkHandleStateUpdatesCallback(t, ml2, 0, expectedLedgerid, expectedStateUpdate, expectedHt)
    87  	txmgr.Commit()
    88  	assert.Equal(t, 1, ml1.StateCommitDoneCallCount())
    89  	assert.Equal(t, 1, ml2.StateCommitDoneCallCount())
    90  	assert.Equal(t, 0, ml3.StateCommitDoneCallCount())
    91  
    92  	// Mimic commit of block 2 with updates only in ns4 namespace
    93  	// This should cause callback only to ml3
    94  	sampleBatch = privacyenabledstate.NewUpdateBatch()
    95  	sampleBatch.PubUpdates.Put("ns4", "key4_1", []byte("value4_1"), version.NewHeight(2, 1))
    96  	sampleBatch.HashUpdates.Put("ns4", "coll1", []byte("key-hash-1"), []byte("value-hash-1"), version.NewHeight(2, 2))
    97  	sampleBatch.HashUpdates.Put("ns4", "coll1", []byte("key-hash-2"), []byte("value-hash-2"), version.NewHeight(2, 2))
    98  	sampleBatch.HashUpdates.Put("ns4", "coll2", []byte("key-hash-3"), []byte("value-hash-3"), version.NewHeight(2, 3))
    99  	sampleBatch.HashUpdates.Delete("ns4", "coll2", []byte("key-hash-4"), version.NewHeight(2, 4))
   100  
   101  	txmgr.current = &current{block: protoutil.NewBlock(2, []byte("anotherDummyHash")), batch: sampleBatch}
   102  	txmgr.invokeNamespaceListeners()
   103  	assert.Equal(t, 1, ml1.HandleStateUpdatesCallCount())
   104  	assert.Equal(t, 1, ml2.HandleStateUpdatesCallCount())
   105  	assert.Equal(t, 1, ml3.HandleStateUpdatesCallCount())
   106  
   107  	expectedLedgerid, expectedStateUpdate, expectedHt =
   108  		testLedgerid,
   109  		ledger.StateUpdates{
   110  			"ns4": &ledger.KVStateUpdates{
   111  				PublicUpdates: []*kvrwset.KVWrite{
   112  					{Key: "key4_1", Value: []byte("value4_1")},
   113  				},
   114  				CollHashUpdates: map[string][]*kvrwset.KVWriteHash{
   115  					"coll1": {
   116  						{KeyHash: []byte("key-hash-1"), ValueHash: []byte("value-hash-1")},
   117  						{KeyHash: []byte("key-hash-2"), ValueHash: []byte("value-hash-2")},
   118  					},
   119  					"coll2": {
   120  						{KeyHash: []byte("key-hash-3"), ValueHash: []byte("value-hash-3")},
   121  						{KeyHash: []byte("key-hash-4"), IsDelete: true},
   122  					},
   123  				},
   124  			},
   125  		},
   126  		uint64(2)
   127  
   128  	checkHandleStateUpdatesCallback(t, ml3, 0, expectedLedgerid, expectedStateUpdate, expectedHt)
   129  
   130  	txmgr.Commit()
   131  	assert.Equal(t, 1, ml1.StateCommitDoneCallCount())
   132  	assert.Equal(t, 1, ml2.StateCommitDoneCallCount())
   133  	assert.Equal(t, 1, ml3.StateCommitDoneCallCount())
   134  }
   135  
   136  func TestStateListenerQueryExecutor(t *testing.T) {
   137  	testEnv := testEnvsMap[levelDBtestEnvName]
   138  	testEnv.init(t, "testLedger", nil)
   139  	defer testEnv.cleanup()
   140  	txMgr := testEnv.getTxMgr().(*LockBasedTxMgr)
   141  
   142  	namespace := "ns"
   143  	populateCollConfigForTest(t, txMgr,
   144  		[]collConfigkey{
   145  			{"ns", "coll"},
   146  		},
   147  		version.NewHeight(1, 0),
   148  	)
   149  
   150  	initialData := []*queryresult.KV{
   151  		{Namespace: namespace, Key: "key1", Value: []byte("value1")},
   152  		{Namespace: namespace, Key: "key2", Value: []byte("value2")},
   153  		{Namespace: namespace, Key: "key3", Value: []byte("value3")},
   154  	}
   155  
   156  	initialPvtdata := []*testutilPvtdata{
   157  		{coll: "coll", key: "key1", value: []byte("value1")},
   158  		{coll: "coll", key: "key2", value: []byte("value2")},
   159  	}
   160  	// populate initial data in db
   161  	testutilPopulateDB(t, txMgr, namespace, initialData, initialPvtdata, version.NewHeight(1, 1))
   162  
   163  	sl := new(mock.StateListener)
   164  	sl.InterestedInNamespacesStub = func() []string { return []string{"ns"} }
   165  	txMgr.stateListeners = []ledger.StateListener{sl}
   166  
   167  	// Create next block
   168  	sim, err := txMgr.NewTxSimulator("tx1")
   169  	assert.NoError(t, err)
   170  	sim.SetState(namespace, "key1", []byte("value1_new"))
   171  	sim.DeleteState(namespace, "key2")
   172  	sim.SetState(namespace, "key4", []byte("value4_new"))
   173  	sim.SetPrivateData(namespace, "coll", "key1", []byte("value1_new")) // change value for key1
   174  	sim.DeletePrivateData(namespace, "coll", "key2")                    // delete key2
   175  	simRes, err := sim.GetTxSimulationResults()
   176  	simResBytes, err := simRes.GetPubSimulationBytes()
   177  	assert.NoError(t, err)
   178  	block := testutil.ConstructBlock(t, 1, nil, [][]byte{simResBytes}, false)
   179  
   180  	// invoke ValidateAndPrepare function
   181  	_, _, err = txMgr.ValidateAndPrepare(&ledger.BlockAndPvtData{Block: block}, false)
   182  	assert.NoError(t, err)
   183  
   184  	// validate that the query executors passed to the state listener
   185  	trigger := sl.HandleStateUpdatesArgsForCall(0)
   186  	assert.NotNil(t, trigger)
   187  	expectedCommittedData := initialData
   188  	checkQueryExecutor(t, trigger.CommittedStateQueryExecutor, namespace, expectedCommittedData)
   189  	expectedCommittedPvtdata := initialPvtdata
   190  	checkQueryExecutorForPvtdataHashes(t, trigger.CommittedStateQueryExecutor, namespace, expectedCommittedPvtdata)
   191  
   192  	expectedPostCommitData := []*queryresult.KV{
   193  		{Namespace: namespace, Key: "key1", Value: []byte("value1_new")},
   194  		{Namespace: namespace, Key: "key3", Value: []byte("value3")},
   195  		{Namespace: namespace, Key: "key4", Value: []byte("value4_new")},
   196  	}
   197  	checkQueryExecutor(t, trigger.PostCommitQueryExecutor, namespace, expectedPostCommitData)
   198  	expectedPostCommitPvtdata := []*testutilPvtdata{
   199  		{coll: "coll", key: "key1", value: []byte("value1_new")},
   200  		{coll: "coll", key: "key2", value: nil},
   201  	}
   202  	checkQueryExecutorForPvtdataHashes(t, trigger.PostCommitQueryExecutor, namespace, expectedPostCommitPvtdata)
   203  }
   204  
   205  func checkHandleStateUpdatesCallback(t *testing.T, ml *mock.StateListener, callNumber int,
   206  	expectedLedgerid string,
   207  	expectedUpdates ledger.StateUpdates,
   208  	expectedCommitHt uint64) {
   209  	actualTrigger := ml.HandleStateUpdatesArgsForCall(callNumber)
   210  	assert.Equal(t, expectedLedgerid, actualTrigger.LedgerID)
   211  	checkEqualUpdates(t, expectedUpdates, actualTrigger.StateUpdates)
   212  	assert.Equal(t, expectedCommitHt, actualTrigger.CommittingBlockNum)
   213  }
   214  
   215  func checkEqualUpdates(t *testing.T, expected, actual ledger.StateUpdates) {
   216  	assert.Equal(t, len(expected), len(actual))
   217  	for ns, e := range expected {
   218  		assert.ElementsMatch(t, e.PublicUpdates, actual[ns].PublicUpdates)
   219  		checkEqualCollsUpdates(t, e.CollHashUpdates, actual[ns].CollHashUpdates)
   220  	}
   221  }
   222  
   223  func checkEqualCollsUpdates(t *testing.T, expected, actual map[string][]*kvrwset.KVWriteHash) {
   224  	assert.Equal(t, len(expected), len(actual))
   225  	for coll, e := range expected {
   226  		assert.ElementsMatch(t, e, actual[coll])
   227  	}
   228  }
   229  
   230  func checkQueryExecutor(t *testing.T, qe ledger.SimpleQueryExecutor, namespace string, expectedResults []*queryresult.KV) {
   231  	for _, kv := range expectedResults {
   232  		val, err := qe.GetState(namespace, kv.Key)
   233  		assert.NoError(t, err)
   234  		assert.Equal(t, kv.Value, val)
   235  	}
   236  
   237  	itr, err := qe.GetStateRangeScanIterator(namespace, "", "")
   238  	assert.NoError(t, err)
   239  	defer itr.Close()
   240  
   241  	actualRes := []*queryresult.KV{}
   242  	for {
   243  		res, err := itr.Next()
   244  		if err != nil {
   245  			assert.NoError(t, err)
   246  		}
   247  		if res == nil {
   248  			break
   249  		}
   250  		actualRes = append(actualRes, res.(*queryresult.KV))
   251  	}
   252  	assert.Equal(t, expectedResults, actualRes)
   253  }
   254  
   255  func checkQueryExecutorForPvtdataHashes(t *testing.T, qe ledger.SimpleQueryExecutor, namespace string, expectedPvtdata []*testutilPvtdata) {
   256  	for _, p := range expectedPvtdata {
   257  		valueHash, err := qe.GetPrivateDataHash(namespace, p.coll, p.key)
   258  		assert.NoError(t, err)
   259  		if p.value == nil {
   260  			assert.Nil(t, valueHash) // key does not exist
   261  		} else {
   262  			assert.Equal(t, util.ComputeHash(p.value), valueHash)
   263  		}
   264  	}
   265  }