github.com/ewagmig/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/queryutil/combiner_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package queryutil_test
     8  
     9  import (
    10  	"errors"
    11  	"os"
    12  	"testing"
    13  
    14  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate"
    15  	"github.com/hyperledger/fabric/core/ledger/util"
    16  
    17  	"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
    18  	"github.com/hyperledger/fabric/common/flogging"
    19  	commonledger "github.com/hyperledger/fabric/common/ledger"
    20  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/queryutil"
    21  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/queryutil/mock"
    22  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
    23  	statedbmock "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/mock"
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestMain(m *testing.M) {
    28  	flogging.ActivateSpec("util,statedb=debug")
    29  	os.Exit(m.Run())
    30  }
    31  
    32  func TestCombinerGetState(t *testing.T) {
    33  	batch1 := statedb.NewUpdateBatch()
    34  	batch1.Put("ns1", "key1", []byte("b1_value1"), nil)
    35  	batch1.Delete("ns1", "key2", nil)
    36  	batch1.Put("ns1", "key3", []byte("b1_value3"), nil)
    37  
    38  	batch2 := statedb.NewUpdateBatch()
    39  	batch2.Put("ns1", "key1", []byte("b2_value1"), nil)
    40  	batch2.Put("ns1", "key2", []byte("b2_value2"), nil)
    41  	batch2.Put("ns1", "key3", []byte("b2_value3"), nil)
    42  
    43  	batch3 := statedb.NewUpdateBatch()
    44  	batch3.Put("ns1", "key1", []byte("b3_value1"), nil)
    45  	batch3.Put("ns1", "key2", []byte("b3_value2"), nil)
    46  	batch3.Delete("ns1", "key3", nil)
    47  
    48  	combiner := &queryutil.QECombiner{
    49  		QueryExecuters: []queryutil.QueryExecuter{
    50  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1},
    51  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2},
    52  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3},
    53  		}}
    54  
    55  	val, err := combiner.GetState("ns1", "key1")
    56  	assert.NoError(t, err)
    57  	assert.Equal(t, []byte("b1_value1"), val)
    58  
    59  	val, err = combiner.GetState("ns1", "key2")
    60  	assert.NoError(t, err)
    61  	assert.Nil(t, val)
    62  
    63  	val, err = combiner.GetState("ns1", "key3")
    64  	assert.NoError(t, err)
    65  	assert.Equal(t, []byte("b1_value3"), val)
    66  
    67  	combiner = &queryutil.QECombiner{
    68  		QueryExecuters: []queryutil.QueryExecuter{
    69  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3},
    70  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2},
    71  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1},
    72  		}}
    73  	val, err = combiner.GetState("ns1", "key1")
    74  	assert.NoError(t, err)
    75  	assert.Equal(t, []byte("b3_value1"), val)
    76  
    77  	val, err = combiner.GetState("ns1", "key2")
    78  	assert.NoError(t, err)
    79  	assert.Equal(t, []byte("b3_value2"), val)
    80  
    81  	val, err = combiner.GetState("ns1", "key3")
    82  	assert.NoError(t, err)
    83  	assert.Nil(t, val)
    84  }
    85  
    86  func TestCombinerRangeScan(t *testing.T) {
    87  	batch1 := statedb.NewUpdateBatch()
    88  	batch1.Put("ns1", "key1", []byte("batch1_value1"), nil)
    89  	batch1.Delete("ns1", "key2", nil)
    90  	batch1.Put("ns1", "key3", []byte("batch1_value3"), nil)
    91  
    92  	batch2 := statedb.NewUpdateBatch()
    93  	batch2.Put("ns1", "key1", []byte("batch2_value1"), nil)
    94  	batch2.Put("ns1", "key2", []byte("batch2_value2"), nil)
    95  	batch2.Delete("ns1", "key3", nil)
    96  	batch2.Put("ns1", "key4", []byte("batch2_value4"), nil)
    97  
    98  	batch3 := statedb.NewUpdateBatch()
    99  	batch3.Put("ns1", "key0", []byte("batch3_value0"), nil)
   100  	batch3.Put("ns1", "key1", []byte("batch3_value1"), nil)
   101  	batch3.Put("ns1", "key2", []byte("batch3_value2"), nil)
   102  	batch3.Put("ns1", "key3", []byte("batch3_value3"), nil)
   103  	batch3.Put("ns1", "key4", []byte("batch3_value4"), nil)
   104  	batch3.Put("ns1", "key5", []byte("batch3_value5"), nil)
   105  
   106  	combiner := &queryutil.QECombiner{
   107  		QueryExecuters: []queryutil.QueryExecuter{
   108  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1},
   109  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2},
   110  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3},
   111  		},
   112  	}
   113  
   114  	itr, err := combiner.GetStateRangeScanIterator("ns1", "key1", "key4")
   115  	assert.NoError(t, err)
   116  	expectedResults := []*queryresult.KV{
   117  		{Namespace: "ns1", Key: "key1", Value: []byte("batch1_value1")},
   118  		{Namespace: "ns1", Key: "key3", Value: []byte("batch1_value3")},
   119  	}
   120  	testutilCheckIteratorResults(t, itr, expectedResults)
   121  
   122  	itr, err = combiner.GetStateRangeScanIterator("ns1", "key0", "key6")
   123  	assert.NoError(t, err)
   124  	expectedResults = []*queryresult.KV{
   125  		{Namespace: "ns1", Key: "key0", Value: []byte("batch3_value0")},
   126  		{Namespace: "ns1", Key: "key1", Value: []byte("batch1_value1")},
   127  		{Namespace: "ns1", Key: "key3", Value: []byte("batch1_value3")},
   128  		{Namespace: "ns1", Key: "key4", Value: []byte("batch2_value4")},
   129  		{Namespace: "ns1", Key: "key5", Value: []byte("batch3_value5")},
   130  	}
   131  	testutilCheckIteratorResults(t, itr, expectedResults)
   132  
   133  	combiner = &queryutil.QECombiner{
   134  		QueryExecuters: []queryutil.QueryExecuter{
   135  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3},
   136  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2},
   137  			&queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1},
   138  		},
   139  	}
   140  	itr, err = combiner.GetStateRangeScanIterator("ns1", "key0", "key6")
   141  	assert.NoError(t, err)
   142  	expectedResults = []*queryresult.KV{
   143  		{Namespace: "ns1", Key: "key0", Value: []byte("batch3_value0")},
   144  		{Namespace: "ns1", Key: "key1", Value: []byte("batch3_value1")},
   145  		{Namespace: "ns1", Key: "key2", Value: []byte("batch3_value2")},
   146  		{Namespace: "ns1", Key: "key3", Value: []byte("batch3_value3")},
   147  		{Namespace: "ns1", Key: "key4", Value: []byte("batch3_value4")},
   148  		{Namespace: "ns1", Key: "key5", Value: []byte("batch3_value5")},
   149  	}
   150  	testutilCheckIteratorResults(t, itr, expectedResults)
   151  }
   152  
   153  func TestGetStateError(t *testing.T) {
   154  	qe1 := &mock.QueryExecuter{}
   155  	qe1.GetStateReturns(&statedb.VersionedValue{Value: []byte("testValue")}, nil)
   156  	qe2 := &mock.QueryExecuter{}
   157  	qe2.GetStateReturns(nil, errors.New("Error for testing"))
   158  	combiner1 := &queryutil.QECombiner{
   159  		QueryExecuters: []queryutil.QueryExecuter{
   160  			qe1, qe2,
   161  		},
   162  	}
   163  	_, err := combiner1.GetState("ns", "key1")
   164  	assert.NoError(t, err)
   165  
   166  	combiner2 := &queryutil.QECombiner{
   167  		QueryExecuters: []queryutil.QueryExecuter{
   168  			qe2, qe1,
   169  		},
   170  	}
   171  	_, err = combiner2.GetState("ns", "key1")
   172  	assert.Error(t, err)
   173  }
   174  
   175  func TestGetRangeScanError(t *testing.T) {
   176  	itr1 := &statedbmock.ResultsIterator{}
   177  	itr1.NextReturns(
   178  		&statedb.VersionedKV{
   179  			CompositeKey:   statedb.CompositeKey{Namespace: "ns", Key: "dummyKey"},
   180  			VersionedValue: statedb.VersionedValue{Value: []byte("dummyVal")},
   181  		},
   182  		nil,
   183  	)
   184  
   185  	qe1 := &mock.QueryExecuter{}
   186  	qe1.GetStateRangeScanIteratorReturns(itr1, nil)
   187  	qe2 := &mock.QueryExecuter{}
   188  	qe2.GetStateRangeScanIteratorReturns(nil, errors.New("dummy error on getting the iterator"))
   189  	combiner := &queryutil.QECombiner{
   190  		QueryExecuters: []queryutil.QueryExecuter{
   191  			qe1, qe2,
   192  		},
   193  	}
   194  	_, err := combiner.GetStateRangeScanIterator("ns", "startKey", "endKey")
   195  	assert.Error(t, err)
   196  }
   197  
   198  func TestGetRangeScanUnderlyingIteratorReturnsError(t *testing.T) {
   199  	itr1 := &statedbmock.ResultsIterator{}
   200  	itr1.NextReturns(
   201  		&statedb.VersionedKV{
   202  			CompositeKey:   statedb.CompositeKey{Namespace: "ns", Key: "dummyKey"},
   203  			VersionedValue: statedb.VersionedValue{Value: []byte("dummyVal")},
   204  		},
   205  		nil,
   206  	)
   207  
   208  	itr2 := &statedbmock.ResultsIterator{}
   209  	itr2.NextReturns(
   210  		nil,
   211  		errors.New("dummyErrorOnIteratorNext"),
   212  	)
   213  
   214  	qe1 := &mock.QueryExecuter{}
   215  	qe1.GetStateRangeScanIteratorReturns(itr1, nil)
   216  	qe2 := &mock.QueryExecuter{}
   217  	qe2.GetStateRangeScanIteratorReturns(itr2, nil)
   218  	combiner := &queryutil.QECombiner{
   219  		QueryExecuters: []queryutil.QueryExecuter{
   220  			qe1, qe2,
   221  		},
   222  	}
   223  	_, err := combiner.GetStateRangeScanIterator("ns", "startKey", "endKey")
   224  	assert.Error(t, err)
   225  }
   226  
   227  func TestGetPrivateDataHash(t *testing.T) {
   228  	batch1 := privacyenabledstate.NewHashedUpdateBatch()
   229  	key1Hash := util.ComputeStringHash("key1")
   230  	key2Hash := util.ComputeStringHash("key2")
   231  	key3Hash := util.ComputeStringHash("key3")
   232  
   233  	batch1.Put("ns1", "coll1", key1Hash, []byte("b1_value1"), nil)
   234  	batch1.Delete("ns1", "coll1", key2Hash, nil)
   235  	batch1.Put("ns1", "coll1", key3Hash, []byte("b1_value3"), nil)
   236  
   237  	batch2 := privacyenabledstate.NewHashedUpdateBatch()
   238  	batch2.Put("ns1", "coll1", key1Hash, []byte("b2_value1"), nil)
   239  	batch2.Put("ns1", "coll1", key2Hash, []byte("b2_value2"), nil)
   240  	batch2.Put("ns1", "coll1", key3Hash, []byte("b2_value3"), nil)
   241  
   242  	batch3 := privacyenabledstate.NewHashedUpdateBatch()
   243  	batch3.Put("ns1", "coll1", key1Hash, []byte("b3_value1"), nil)
   244  	batch3.Put("ns1", "coll1", key2Hash, []byte("b3_value2"), nil)
   245  
   246  	combiner := &queryutil.QECombiner{
   247  		QueryExecuters: []queryutil.QueryExecuter{
   248  			&queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch1},
   249  			&queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch2},
   250  			&queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch3},
   251  		}}
   252  
   253  	val, err := combiner.GetPrivateDataHash("ns1", "coll1", "key1")
   254  	assert.NoError(t, err)
   255  	assert.Equal(t, []byte("b1_value1"), val)
   256  
   257  	val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key2")
   258  	assert.NoError(t, err)
   259  	assert.Nil(t, val)
   260  
   261  	val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key3")
   262  	assert.NoError(t, err)
   263  	assert.Equal(t, []byte("b1_value3"), val)
   264  
   265  	combiner = &queryutil.QECombiner{
   266  		QueryExecuters: []queryutil.QueryExecuter{
   267  			&queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch3},
   268  			&queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch2},
   269  			&queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch1},
   270  		}}
   271  	val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key1")
   272  	assert.NoError(t, err)
   273  	assert.Equal(t, []byte("b3_value1"), val)
   274  
   275  	val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key2")
   276  	assert.NoError(t, err)
   277  	assert.Equal(t, []byte("b3_value2"), val)
   278  
   279  	val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key3")
   280  	assert.NoError(t, err)
   281  	assert.Equal(t, []byte("b2_value3"), val)
   282  }
   283  
   284  func TestGetPrivateDataHashError(t *testing.T) {
   285  	qe1 := &mock.QueryExecuter{}
   286  	qe1.GetPrivateDataHashReturns(&statedb.VersionedValue{Value: []byte("testValue")}, nil)
   287  	qe2 := &mock.QueryExecuter{}
   288  	qe2.GetPrivateDataHashReturns(nil, errors.New("Error for testing"))
   289  	combiner1 := &queryutil.QECombiner{
   290  		QueryExecuters: []queryutil.QueryExecuter{
   291  			qe1, qe2,
   292  		},
   293  	}
   294  	_, err := combiner1.GetPrivateDataHash("ns", "coll1", "key1")
   295  	assert.NoError(t, err)
   296  
   297  	combiner2 := &queryutil.QECombiner{
   298  		QueryExecuters: []queryutil.QueryExecuter{
   299  			qe2, qe1,
   300  		},
   301  	}
   302  	_, err = combiner2.GetPrivateDataHash("ns", "coll1", "key1")
   303  	assert.Error(t, err)
   304  }
   305  
   306  func testutilCheckIteratorResults(t *testing.T, itr commonledger.ResultsIterator, expectedResults []*queryresult.KV) {
   307  	results := []*queryresult.KV{}
   308  	for {
   309  		result, err := itr.Next()
   310  		assert.NoError(t, err)
   311  		if result == nil {
   312  			break
   313  		}
   314  		results = append(results, result.(*queryresult.KV))
   315  	}
   316  	assert.Equal(t, expectedResults, results)
   317  }