github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/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 kvledger
     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/bccsp/sw"
    15  	"github.com/hyperledger/fabric/common/ledger/testutil"
    16  	"github.com/hyperledger/fabric/common/metrics/disabled"
    17  	"github.com/hyperledger/fabric/core/ledger"
    18  	"github.com/hyperledger/fabric/core/ledger/mock"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  func TestStateListener(t *testing.T) {
    23  	conf, cleanup := testConfig(t)
    24  	defer cleanup()
    25  
    26  	// create a listener and register it to listen to state change in a namespace
    27  	channelid := "testLedger"
    28  	namespace := "testchaincode"
    29  	mockListener := &mockStateListener{namespace: namespace}
    30  
    31  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    32  	assert.NoError(t, err)
    33  	provider, err := NewProvider(
    34  		&ledger.Initializer{
    35  			DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{},
    36  			StateListeners:                []ledger.StateListener{mockListener},
    37  			MetricsProvider:               &disabled.Provider{},
    38  			Config:                        conf,
    39  			Hasher:                        cryptoProvider,
    40  		},
    41  	)
    42  	if err != nil {
    43  		t.Fatalf("Failed to create new Provider: %s", err)
    44  	}
    45  
    46  	bg, gb := testutil.NewBlockGenerator(t, channelid, false)
    47  	lgr, err := provider.Create(gb)
    48  	// Simulate tx1
    49  	sim1, err := lgr.NewTxSimulator("test_tx_1")
    50  	assert.NoError(t, err)
    51  	sim1.GetState(namespace, "key1")
    52  	sim1.SetState(namespace, "key1", []byte("value1"))
    53  	sim1.SetState(namespace, "key2", []byte("value2"))
    54  	sim1.Done()
    55  
    56  	// Simulate tx2 - this has a conflict with tx1 because it reads "key1"
    57  	sim2, err := lgr.NewTxSimulator("test_tx_2")
    58  	assert.NoError(t, err)
    59  	sim2.GetState(namespace, "key1")
    60  	sim2.SetState(namespace, "key3", []byte("value3"))
    61  	sim2.Done()
    62  
    63  	// Simulate tx3 - this neighter conflicts with tx1 nor with tx2
    64  	sim3, err := lgr.NewTxSimulator("test_tx_3")
    65  	assert.NoError(t, err)
    66  	sim3.SetState(namespace, "key4", []byte("value4"))
    67  	sim3.Done()
    68  
    69  	// commit tx1 and this should cause mock listener to recieve the state changes made by tx1
    70  	mockListener.reset()
    71  	sim1Res, _ := sim1.GetTxSimulationResults()
    72  	sim1ResBytes, _ := sim1Res.GetPubSimulationBytes()
    73  	assert.NoError(t, err)
    74  	blk1 := bg.NextBlock([][]byte{sim1ResBytes})
    75  	assert.NoError(t, lgr.CommitLegacy(&ledger.BlockAndPvtData{Block: blk1}, &ledger.CommitOptions{}))
    76  	assert.Equal(t, channelid, mockListener.channelName)
    77  	assert.Contains(t, mockListener.kvWrites, &kvrwset.KVWrite{Key: "key1", Value: []byte("value1")})
    78  	assert.Contains(t, mockListener.kvWrites, &kvrwset.KVWrite{Key: "key2", Value: []byte("value2")})
    79  	// commit tx2 and this should not cause mock listener to recieve the state changes made by tx2
    80  	// (because, tx2 should be found as invalid)
    81  	mockListener.reset()
    82  	sim2Res, _ := sim2.GetTxSimulationResults()
    83  	sim2ResBytes, _ := sim2Res.GetPubSimulationBytes()
    84  	assert.NoError(t, err)
    85  	blk2 := bg.NextBlock([][]byte{sim2ResBytes})
    86  	assert.NoError(t, lgr.CommitLegacy(&ledger.BlockAndPvtData{Block: blk2}, &ledger.CommitOptions{}))
    87  	assert.Equal(t, "", mockListener.channelName)
    88  	assert.Nil(t, mockListener.kvWrites)
    89  
    90  	// commit tx3 and this should cause mock listener to recieve changes made by tx3
    91  	mockListener.reset()
    92  	sim3Res, _ := sim3.GetTxSimulationResults()
    93  	sim3ResBytes, _ := sim3Res.GetPubSimulationBytes()
    94  	assert.NoError(t, err)
    95  	blk3 := bg.NextBlock([][]byte{sim3ResBytes})
    96  	assert.NoError(t, lgr.CommitLegacy(&ledger.BlockAndPvtData{Block: blk3}, &ledger.CommitOptions{}))
    97  	assert.Equal(t, channelid, mockListener.channelName)
    98  	assert.Equal(t, []*kvrwset.KVWrite{
    99  		{Key: "key4", Value: []byte("value4")},
   100  	}, mockListener.kvWrites)
   101  
   102  	provider.Close()
   103  
   104  	provider, err = NewProvider(
   105  		&ledger.Initializer{
   106  			DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{},
   107  			StateListeners:                []ledger.StateListener{mockListener},
   108  			MetricsProvider:               &disabled.Provider{},
   109  			Config:                        conf,
   110  			Hasher:                        cryptoProvider,
   111  		},
   112  	)
   113  	if err != nil {
   114  		t.Fatalf("Failed to create new Provider: %s", err)
   115  	}
   116  	defer provider.Close()
   117  	lgr, err = provider.Open(channelid)
   118  	assert.NoError(t, err)
   119  	defer lgr.Close()
   120  	assert.NoError(t, err)
   121  	assert.Equal(t,
   122  		[]*queryresult.KV{
   123  			{
   124  				Namespace: namespace,
   125  				Key:       "key1",
   126  				Value:     []byte("value1"),
   127  			},
   128  			{
   129  				Namespace: namespace,
   130  				Key:       "key2",
   131  				Value:     []byte("value2"),
   132  			},
   133  			{
   134  				Namespace: namespace,
   135  				Key:       "key4",
   136  				Value:     []byte("value4"),
   137  			},
   138  		},
   139  		mockListener.queryResultsInInitializeFunc,
   140  	)
   141  }
   142  
   143  type mockStateListener struct {
   144  	channelName                  string
   145  	namespace                    string
   146  	kvWrites                     []*kvrwset.KVWrite
   147  	queryResultsInInitializeFunc []*queryresult.KV
   148  }
   149  
   150  func (l *mockStateListener) Initialize(ledgerID string, qe ledger.SimpleQueryExecutor) error {
   151  	_, err := qe.GetPrivateDataHash(l.namespace, "random-coll", "random-key")
   152  	if err != nil {
   153  		return err
   154  	}
   155  	l.channelName = ledgerID
   156  	itr, err := qe.GetStateRangeScanIterator(l.namespace, "", "")
   157  	if err != nil {
   158  		return err
   159  	}
   160  	for {
   161  		res, err := itr.Next()
   162  		if err != nil {
   163  			return err
   164  		}
   165  		if res == nil {
   166  			break
   167  		}
   168  		kv := res.(*queryresult.KV)
   169  		l.queryResultsInInitializeFunc = append(l.queryResultsInInitializeFunc,
   170  			kv,
   171  		)
   172  	}
   173  	return nil
   174  }
   175  
   176  func (l *mockStateListener) InterestedInNamespaces() []string {
   177  	return []string{l.namespace}
   178  }
   179  
   180  func (l *mockStateListener) HandleStateUpdates(trigger *ledger.StateUpdateTrigger) error {
   181  	channelName, stateUpdates := trigger.LedgerID, trigger.StateUpdates
   182  	l.channelName = channelName
   183  	l.kvWrites = stateUpdates[l.namespace].PublicUpdates
   184  	return nil
   185  }
   186  
   187  func (l *mockStateListener) StateCommitDone(channelID string) {
   188  	// NOOP
   189  }
   190  
   191  func (l *mockStateListener) reset() {
   192  	l.channelName = ""
   193  	l.kvWrites = nil
   194  	l.queryResultsInInitializeFunc = nil
   195  }