github.com/ewagmig/fabric@v2.1.1+incompatible/core/ledger/kvledger/tests/verifier.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tests
     8  
     9  import (
    10  	"testing"
    11  
    12  	"github.com/davecgh/go-spew/spew"
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    16  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    17  	protopeer "github.com/hyperledger/fabric-protos-go/peer"
    18  	"github.com/hyperledger/fabric/core/ledger"
    19  	lgrutil "github.com/hyperledger/fabric/core/ledger/util"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  // verifier provides functions that help tests with less verbose code for querying the ledger
    24  // and verifying the actual results with the expected results
    25  // For the straight forward functions, tests can call them directly on the ledger
    26  type verifier struct {
    27  	lgr    ledger.PeerLedger
    28  	assert *assert.Assertions
    29  	t      *testing.T
    30  }
    31  
    32  func newVerifier(lgr ledger.PeerLedger, t *testing.T) *verifier {
    33  	return &verifier{lgr, assert.New(t), t}
    34  }
    35  
    36  func (v *verifier) verifyLedgerHeight(expectedHt uint64) {
    37  	info, err := v.lgr.GetBlockchainInfo()
    38  	v.assert.NoError(err)
    39  	v.assert.Equal(expectedHt, info.Height)
    40  }
    41  
    42  func (v *verifier) verifyPubState(ns, key string, expectedVal string) {
    43  	qe, err := v.lgr.NewQueryExecutor()
    44  	v.assert.NoError(err)
    45  	defer qe.Done()
    46  	committedVal, err := qe.GetState(ns, key)
    47  	v.assert.NoError(err)
    48  	v.t.Logf("val=%s", committedVal)
    49  	var expectedValBytes []byte
    50  	if expectedVal != "" {
    51  		expectedValBytes = []byte(expectedVal)
    52  	}
    53  	v.assert.Equal(expectedValBytes, committedVal)
    54  }
    55  
    56  func (v *verifier) verifyPvtState(ns, coll, key string, expectedVal string) {
    57  	qe, err := v.lgr.NewQueryExecutor()
    58  	v.assert.NoError(err)
    59  	defer qe.Done()
    60  	committedVal, err := qe.GetPrivateData(ns, coll, key)
    61  	v.assert.NoError(err)
    62  	v.t.Logf("val=%s", committedVal)
    63  	var expectedValBytes []byte
    64  	if expectedVal != "" {
    65  		expectedValBytes = []byte(expectedVal)
    66  	}
    67  	v.assert.Equal(expectedValBytes, committedVal)
    68  }
    69  
    70  func (v *verifier) verifyMostRecentCollectionConfigBelow(blockNum uint64, chaincodeName string, expectOut *expectedCollConfInfo) {
    71  	configHistory, err := v.lgr.GetConfigHistoryRetriever()
    72  	v.assert.NoError(err)
    73  	actualCollectionConfigInfo, err := configHistory.MostRecentCollectionConfigBelow(blockNum, chaincodeName)
    74  	v.assert.NoError(err)
    75  	if expectOut == nil {
    76  		v.assert.Nil(actualCollectionConfigInfo)
    77  		return
    78  	}
    79  	v.t.Logf("Retrieved CollectionConfigInfo=%s", spew.Sdump(actualCollectionConfigInfo))
    80  	actualCommittingBlockNum := actualCollectionConfigInfo.CommittingBlockNum
    81  	actualCollConf := convertFromCollConfigProto(actualCollectionConfigInfo.CollectionConfig)
    82  	v.assert.Equal(expectOut.committingBlockNum, actualCommittingBlockNum)
    83  	v.assert.Equal(expectOut.collConfs, actualCollConf)
    84  }
    85  
    86  func (v *verifier) verifyBlockAndPvtData(blockNum uint64, filter ledger.PvtNsCollFilter, verifyLogic func(r *retrievedBlockAndPvtdata)) {
    87  	out, err := v.lgr.GetPvtDataAndBlockByNum(blockNum, filter)
    88  	v.assert.NoError(err)
    89  	v.t.Logf("Retrieved Block = %s, pvtdata = %s", spew.Sdump(out.Block), spew.Sdump(out.PvtData))
    90  	verifyLogic(&retrievedBlockAndPvtdata{out, v.assert})
    91  }
    92  
    93  func (v *verifier) verifyBlockAndPvtDataSameAs(blockNum uint64, expectedOut *ledger.BlockAndPvtData) {
    94  	v.verifyBlockAndPvtData(blockNum, nil, func(r *retrievedBlockAndPvtdata) {
    95  		r.sameAs(expectedOut)
    96  	})
    97  }
    98  
    99  func (v *verifier) verifyMissingPvtDataSameAs(recentNBlocks int, expectedMissingData ledger.MissingPvtDataInfo) {
   100  	missingDataTracker, err := v.lgr.GetMissingPvtDataTracker()
   101  	v.assert.NoError(err)
   102  	missingPvtData, err := missingDataTracker.GetMissingPvtDataInfoForMostRecentBlocks(recentNBlocks)
   103  	v.assert.NoError(err)
   104  	v.assert.Equal(expectedMissingData, missingPvtData)
   105  }
   106  
   107  func (v *verifier) verifyGetTransactionByID(txid string, expectedOut *protopeer.ProcessedTransaction) {
   108  	tran, err := v.lgr.GetTransactionByID(txid)
   109  	v.assert.NoError(err)
   110  	envelopEqual := proto.Equal(expectedOut.TransactionEnvelope, tran.TransactionEnvelope)
   111  	v.assert.True(envelopEqual)
   112  	v.assert.Equal(expectedOut.ValidationCode, tran.ValidationCode)
   113  }
   114  
   115  func (v *verifier) verifyTxValidationCode(txid string, expectedCode protopeer.TxValidationCode) {
   116  	tran, err := v.lgr.GetTransactionByID(txid)
   117  	v.assert.NoError(err)
   118  	v.assert.Equal(int32(expectedCode), tran.ValidationCode)
   119  }
   120  
   121  func (v *verifier) verifyHistory(ns, key string, expectedVals []string) {
   122  	hqe, err := v.lgr.NewHistoryQueryExecutor()
   123  	v.assert.NoError(err)
   124  	itr, err := hqe.GetHistoryForKey(ns, key)
   125  	v.assert.NoError(err)
   126  	historyValues := []string{}
   127  	for {
   128  		result, err := itr.Next()
   129  		v.assert.NoError(err)
   130  		if result == nil {
   131  			break
   132  		}
   133  		historyValues = append(historyValues, string(result.(*queryresult.KeyModification).GetValue()))
   134  	}
   135  	v.assert.Equal(expectedVals, historyValues)
   136  }
   137  
   138  ////////////  structs used by verifier  //////////////////////////////////////////////////////////////
   139  type expectedCollConfInfo struct {
   140  	committingBlockNum uint64
   141  	collConfs          []*collConf
   142  }
   143  
   144  type retrievedBlockAndPvtdata struct {
   145  	*ledger.BlockAndPvtData
   146  	assert *assert.Assertions
   147  }
   148  
   149  func (r *retrievedBlockAndPvtdata) sameAs(expectedBlockAndPvtdata *ledger.BlockAndPvtData) {
   150  	r.samePvtdata(expectedBlockAndPvtdata.PvtData)
   151  	r.sameBlockHeaderAndData(expectedBlockAndPvtdata.Block)
   152  	r.sameMetadata(expectedBlockAndPvtdata.Block)
   153  }
   154  
   155  func (r *retrievedBlockAndPvtdata) hasNumTx(numTx int) {
   156  	r.assert.Len(r.Block.Data.Data, numTx)
   157  }
   158  
   159  func (r *retrievedBlockAndPvtdata) hasNoPvtdata() {
   160  	r.assert.Len(r.PvtData, 0)
   161  }
   162  
   163  func (r *retrievedBlockAndPvtdata) pvtdataShouldContain(txSeq int, ns, coll, key, value string) {
   164  	txPvtData := r.BlockAndPvtData.PvtData[uint64(txSeq)]
   165  	for _, nsdata := range txPvtData.WriteSet.NsPvtRwset {
   166  		if nsdata.Namespace == ns {
   167  			for _, colldata := range nsdata.CollectionPvtRwset {
   168  				if colldata.CollectionName == coll {
   169  					rwset := &kvrwset.KVRWSet{}
   170  					r.assert.NoError(proto.Unmarshal(colldata.Rwset, rwset))
   171  					for _, w := range rwset.Writes {
   172  						if w.Key == key {
   173  							r.assert.Equal([]byte(value), w.Value)
   174  							return
   175  						}
   176  					}
   177  				}
   178  			}
   179  		}
   180  	}
   181  	r.assert.FailNow("Requested kv not found")
   182  }
   183  
   184  func (r *retrievedBlockAndPvtdata) pvtdataShouldNotContain(ns, coll string) {
   185  	allTxPvtData := r.BlockAndPvtData.PvtData
   186  	for _, txPvtData := range allTxPvtData {
   187  		r.assert.False(txPvtData.Has(ns, coll))
   188  	}
   189  }
   190  
   191  func (r *retrievedBlockAndPvtdata) sameBlockHeaderAndData(expectedBlock *common.Block) {
   192  	r.assert.True(proto.Equal(expectedBlock.Data, r.BlockAndPvtData.Block.Data))
   193  	r.assert.True(proto.Equal(expectedBlock.Header, r.BlockAndPvtData.Block.Header))
   194  }
   195  
   196  func (r *retrievedBlockAndPvtdata) sameMetadata(expectedBlock *common.Block) {
   197  	// marshalling/unmarshalling treats a nil byte and empty byte interchangeably (based on which scheme is chosen proto vs gob)
   198  	// so explicitly comparing each metadata
   199  	retrievedMetadata := r.Block.Metadata.Metadata
   200  	expectedMetadata := expectedBlock.Metadata.Metadata
   201  	r.assert.Equal(len(expectedMetadata), len(retrievedMetadata))
   202  	for i := 0; i < len(expectedMetadata); i++ {
   203  		if len(expectedMetadata[i])+len(retrievedMetadata[i]) != 0 {
   204  			if i != int(common.BlockMetadataIndex_COMMIT_HASH) {
   205  				r.assert.Equal(expectedMetadata[i], retrievedMetadata[i])
   206  			} else {
   207  				// in order to compare the exact hash value, we need to duplicate the
   208  				// production code in this test too (which is not recommended).
   209  				commitHash := &common.Metadata{}
   210  				err := proto.Unmarshal(retrievedMetadata[common.BlockMetadataIndex_COMMIT_HASH],
   211  					commitHash)
   212  				r.assert.NoError(err)
   213  				r.assert.Equal(len(commitHash.Value), 32)
   214  			}
   215  		}
   216  	}
   217  }
   218  
   219  func (r *retrievedBlockAndPvtdata) containsValidationCode(txSeq int, validationCode protopeer.TxValidationCode) {
   220  	var txFilter lgrutil.TxValidationFlags
   221  	txFilter = r.BlockAndPvtData.Block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]
   222  	r.assert.Equal(validationCode, txFilter.Flag(txSeq))
   223  }
   224  
   225  func (r *retrievedBlockAndPvtdata) samePvtdata(expectedPvtdata map[uint64]*ledger.TxPvtData) {
   226  	r.assert.Equal(len(expectedPvtdata), len(r.BlockAndPvtData.PvtData))
   227  	for txNum, pvtData := range expectedPvtdata {
   228  		actualPvtData := r.BlockAndPvtData.PvtData[txNum]
   229  		r.assert.Equal(pvtData.SeqInBlock, actualPvtData.SeqInBlock)
   230  		r.assert.True(proto.Equal(pvtData.WriteSet, actualPvtData.WriteSet))
   231  	}
   232  }