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

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package statedb
     8  
     9  import (
    10  	"sort"
    11  	"testing"
    12  
    13  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestPanic(t *testing.T) {
    18  	defer func() {
    19  		if r := recover(); r == nil {
    20  			t.Fatalf("Nil value to Put() did not panic\n")
    21  		}
    22  	}()
    23  
    24  	batch := NewUpdateBatch()
    25  	// The following call to Put() should result in panic
    26  	batch.Put("ns1", "key1", nil, nil)
    27  }
    28  
    29  //Test Put(), Get(), and Delete()
    30  func TestPutGetDeleteExistsGetUpdates(t *testing.T) {
    31  	batch := NewUpdateBatch()
    32  	batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1))
    33  
    34  	//Get() should return above inserted <k,v> pair
    35  	actualVersionedValue := batch.Get("ns1", "key1")
    36  	assert.Equal(t, &VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)}, actualVersionedValue)
    37  	//Exists() should return false as key2 does not exist
    38  	actualResult := batch.Exists("ns1", "key2")
    39  	expectedResult := false
    40  	assert.Equal(t, expectedResult, actualResult)
    41  
    42  	//Exists() should return false as ns3 does not exist
    43  	actualResult = batch.Exists("ns3", "key2")
    44  	expectedResult = false
    45  	assert.Equal(t, expectedResult, actualResult)
    46  
    47  	//Get() should return nil as key2 does not exist
    48  	actualVersionedValue = batch.Get("ns1", "key2")
    49  	assert.Nil(t, actualVersionedValue)
    50  	//Get() should return nil as ns3 does not exist
    51  	actualVersionedValue = batch.Get("ns3", "key2")
    52  	assert.Nil(t, actualVersionedValue)
    53  
    54  	batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2))
    55  	//Exists() should return true as key2 exists
    56  	actualResult = batch.Exists("ns1", "key2")
    57  	expectedResult = true
    58  	assert.Equal(t, expectedResult, actualResult)
    59  
    60  	//GetUpdatedNamespaces should return 3 namespaces
    61  	batch.Put("ns2", "key2", []byte("value2"), version.NewHeight(1, 2))
    62  	batch.Put("ns3", "key2", []byte("value2"), version.NewHeight(1, 2))
    63  	actualNamespaces := batch.GetUpdatedNamespaces()
    64  	sort.Strings(actualNamespaces)
    65  	expectedNamespaces := []string{"ns1", "ns2", "ns3"}
    66  	assert.Equal(t, expectedNamespaces, actualNamespaces)
    67  
    68  	//GetUpdates should return two VersionedValues for the namespace ns1
    69  	expectedUpdates := make(map[string]*VersionedValue)
    70  	expectedUpdates["key1"] = &VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)}
    71  	expectedUpdates["key2"] = &VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)}
    72  	actualUpdates := batch.GetUpdates("ns1")
    73  	assert.Equal(t, expectedUpdates, actualUpdates)
    74  
    75  	actualUpdates = batch.GetUpdates("ns4")
    76  	assert.Nil(t, actualUpdates)
    77  
    78  	//Delete the above inserted <k,v> pair
    79  	batch.Delete("ns1", "key2", version.NewHeight(1, 2))
    80  	//Exists() should return true after deleting key2
    81  	//Exists() should return true iff the key has action(Put/Delete) in this batch
    82  	actualResult = batch.Exists("ns1", "key2")
    83  	expectedResult = true
    84  	assert.Equal(t, expectedResult, actualResult)
    85  
    86  }
    87  
    88  func TestUpdateBatchIterator(t *testing.T) {
    89  	batch := NewUpdateBatch()
    90  	batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1))
    91  	batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2))
    92  	batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 3))
    93  
    94  	batch.Put("ns2", "key6", []byte("value6"), version.NewHeight(2, 3))
    95  	batch.Put("ns2", "key5", []byte("value5"), version.NewHeight(2, 2))
    96  	batch.Put("ns2", "key4", []byte("value4"), version.NewHeight(2, 1))
    97  
    98  	checkItrResults(t, batch.GetRangeScanIterator("ns1", "key2", "key3"), []*VersionedKV{
    99  		{CompositeKey{"ns1", "key2"}, VersionedValue{[]byte("value2"), nil, version.NewHeight(1, 2)}},
   100  	})
   101  
   102  	checkItrResults(t, batch.GetRangeScanIterator("ns2", "key0", "key8"), []*VersionedKV{
   103  		{CompositeKey{"ns2", "key4"}, VersionedValue{[]byte("value4"), nil, version.NewHeight(2, 1)}},
   104  		{CompositeKey{"ns2", "key5"}, VersionedValue{[]byte("value5"), nil, version.NewHeight(2, 2)}},
   105  		{CompositeKey{"ns2", "key6"}, VersionedValue{[]byte("value6"), nil, version.NewHeight(2, 3)}},
   106  	})
   107  
   108  	checkItrResults(t, batch.GetRangeScanIterator("ns2", "", ""), []*VersionedKV{
   109  		{CompositeKey{"ns2", "key4"}, VersionedValue{[]byte("value4"), nil, version.NewHeight(2, 1)}},
   110  		{CompositeKey{"ns2", "key5"}, VersionedValue{[]byte("value5"), nil, version.NewHeight(2, 2)}},
   111  		{CompositeKey{"ns2", "key6"}, VersionedValue{[]byte("value6"), nil, version.NewHeight(2, 3)}},
   112  	})
   113  
   114  	checkItrResults(t, batch.GetRangeScanIterator("non-existing-ns", "", ""), nil)
   115  }
   116  
   117  func checkItrResults(t *testing.T, itr QueryResultsIterator, expectedResults []*VersionedKV) {
   118  	for i := 0; i < len(expectedResults); i++ {
   119  		res, _ := itr.Next()
   120  		assert.Equal(t, expectedResults[i], res)
   121  	}
   122  	lastRes, err := itr.Next()
   123  	assert.NoError(t, err)
   124  	assert.Nil(t, lastRes)
   125  	itr.Close()
   126  }
   127  
   128  // TestPaginatedRangeValidation tests queries with pagination
   129  func TestPaginatedRangeValidation(t *testing.T) {
   130  
   131  	queryOptions := make(map[string]interface{})
   132  	queryOptions["limit"] = int32(10)
   133  
   134  	err := ValidateRangeMetadata(queryOptions)
   135  	assert.NoError(t, err, "An error was thrown for a valid option")
   136  
   137  	queryOptions = make(map[string]interface{})
   138  	queryOptions["limit"] = float32(10.2)
   139  
   140  	err = ValidateRangeMetadata(queryOptions)
   141  	assert.Error(t, err, "An should have been thrown for an invalid option")
   142  
   143  	queryOptions = make(map[string]interface{})
   144  	queryOptions["limit"] = "10"
   145  
   146  	err = ValidateRangeMetadata(queryOptions)
   147  	assert.Error(t, err, "An should have been thrown for an invalid option")
   148  
   149  	queryOptions = make(map[string]interface{})
   150  	queryOptions["limit1"] = int32(10)
   151  
   152  	err = ValidateRangeMetadata(queryOptions)
   153  	assert.Error(t, err, "An should have been thrown for an invalid option")
   154  
   155  }
   156  
   157  func TestMergeUpdateBatch(t *testing.T) {
   158  	batch1 := NewUpdateBatch()
   159  	batch1.Put("ns1", "key1", []byte("batch1_value1"), version.NewHeight(1, 1))
   160  	batch1.Put("ns1", "key2", []byte("batch1_value2"), version.NewHeight(2, 2))
   161  	batch1.Put("ns1", "key3", []byte("batch1_value3"), version.NewHeight(3, 3))
   162  
   163  	batch2 := NewUpdateBatch()
   164  	batch2.ContainsPostOrderWrites = true
   165  	batch2.Put("ns1", "key1", []byte("batch2_value1"), version.NewHeight(4, 4)) // overwrite key1 with new value
   166  	batch2.Delete("ns1", "key2", version.NewHeight(5, 5))                       // overwrite key2 with deletion
   167  	batch2.Put("ns1", "key4", []byte("batch2_value4"), version.NewHeight(6, 6)) // new key only in batch2
   168  	batch2.Delete("ns1", "key5", version.NewHeight(7, 7))                       // delete key only in batch2
   169  	batch2.Put("ns2", "key6", []byte("batch2_value6"), version.NewHeight(8, 8)) // namespace only in batch2
   170  
   171  	batch1.Merge(batch2)
   172  
   173  	// prepare final expected batch by writing all updates in the above order
   174  	expectedBatch := NewUpdateBatch()
   175  	expectedBatch.ContainsPostOrderWrites = true
   176  	expectedBatch.Put("ns1", "key1", []byte("batch1_value1"), version.NewHeight(1, 1))
   177  	expectedBatch.Put("ns1", "key2", []byte("batch1_value2"), version.NewHeight(2, 2))
   178  	expectedBatch.Put("ns1", "key3", []byte("batch1_value3"), version.NewHeight(3, 3))
   179  	expectedBatch.Put("ns1", "key1", []byte("batch2_value1"), version.NewHeight(4, 4))
   180  	expectedBatch.Delete("ns1", "key2", version.NewHeight(5, 5))
   181  	expectedBatch.Put("ns1", "key4", []byte("batch2_value4"), version.NewHeight(6, 6))
   182  	expectedBatch.Delete("ns1", "key5", version.NewHeight(7, 7))
   183  	expectedBatch.Put("ns2", "key6", []byte("batch2_value6"), version.NewHeight(8, 8))
   184  	assert.Equal(t, expectedBatch, batch1)
   185  }