github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/statedb/statedb_test.go (about)

     1  /*
     2  Copyright hechain. 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/hechain20/hechain/core/ledger/internal/version"
    14  	"github.com/stretchr/testify/require"
    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  	require.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  	require.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  	require.Equal(t, expectedResult, actualResult)
    46  
    47  	// Get() should return nil as key2 does not exist
    48  	actualVersionedValue = batch.Get("ns1", "key2")
    49  	require.Nil(t, actualVersionedValue)
    50  	// Get() should return nil as ns3 does not exist
    51  	actualVersionedValue = batch.Get("ns3", "key2")
    52  	require.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  	require.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  	require.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  	require.Equal(t, expectedUpdates, actualUpdates)
    74  
    75  	actualUpdates = batch.GetUpdates("ns4")
    76  	require.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  	require.Equal(t, expectedResult, actualResult)
    85  }
    86  
    87  func TestUpdateBatchIterator(t *testing.T) {
    88  	batch := NewUpdateBatch()
    89  	batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1))
    90  	batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2))
    91  	batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 3))
    92  
    93  	batch.Put("ns2", "key6", []byte("value6"), version.NewHeight(2, 3))
    94  	batch.Put("ns2", "key5", []byte("value5"), version.NewHeight(2, 2))
    95  	batch.Put("ns2", "key4", []byte("value4"), version.NewHeight(2, 1))
    96  
    97  	checkItrResults(t, batch.GetRangeScanIterator("ns1", "key2", "key3"), []*VersionedKV{
    98  		{
    99  			&CompositeKey{"ns1", "key2"},
   100  			&VersionedValue{[]byte("value2"), nil, version.NewHeight(1, 2)},
   101  		},
   102  	})
   103  
   104  	checkItrResults(t, batch.GetRangeScanIterator("ns2", "key0", "key8"), []*VersionedKV{
   105  		{
   106  			&CompositeKey{"ns2", "key4"},
   107  			&VersionedValue{[]byte("value4"), nil, version.NewHeight(2, 1)},
   108  		},
   109  		{
   110  			&CompositeKey{"ns2", "key5"},
   111  			&VersionedValue{[]byte("value5"), nil, version.NewHeight(2, 2)},
   112  		},
   113  		{
   114  			&CompositeKey{"ns2", "key6"},
   115  			&VersionedValue{[]byte("value6"), nil, version.NewHeight(2, 3)},
   116  		},
   117  	})
   118  
   119  	checkItrResults(t, batch.GetRangeScanIterator("ns2", "", ""), []*VersionedKV{
   120  		{
   121  			&CompositeKey{"ns2", "key4"},
   122  			&VersionedValue{[]byte("value4"), nil, version.NewHeight(2, 1)},
   123  		},
   124  		{
   125  			&CompositeKey{"ns2", "key5"},
   126  			&VersionedValue{[]byte("value5"), nil, version.NewHeight(2, 2)},
   127  		},
   128  		{
   129  			&CompositeKey{"ns2", "key6"},
   130  			&VersionedValue{[]byte("value6"), nil, version.NewHeight(2, 3)},
   131  		},
   132  	})
   133  
   134  	checkItrResults(t, batch.GetRangeScanIterator("non-existing-ns", "", ""), nil)
   135  }
   136  
   137  func checkItrResults(t *testing.T, itr QueryResultsIterator, expectedResults []*VersionedKV) {
   138  	for i := 0; i < len(expectedResults); i++ {
   139  		res, _ := itr.Next()
   140  		require.Equal(t, expectedResults[i], res)
   141  	}
   142  	lastRes, err := itr.Next()
   143  	require.NoError(t, err)
   144  	require.Nil(t, lastRes)
   145  	itr.Close()
   146  }
   147  
   148  func TestMergeUpdateBatch(t *testing.T) {
   149  	batch1 := NewUpdateBatch()
   150  	batch1.Put("ns1", "key1", []byte("batch1_value1"), version.NewHeight(1, 1))
   151  	batch1.Put("ns1", "key2", []byte("batch1_value2"), version.NewHeight(2, 2))
   152  	batch1.Put("ns1", "key3", []byte("batch1_value3"), version.NewHeight(3, 3))
   153  
   154  	batch2 := NewUpdateBatch()
   155  	batch2.ContainsPostOrderWrites = true
   156  	batch2.Put("ns1", "key1", []byte("batch2_value1"), version.NewHeight(4, 4)) // overwrite key1 with new value
   157  	batch2.Delete("ns1", "key2", version.NewHeight(5, 5))                       // overwrite key2 with deletion
   158  	batch2.Put("ns1", "key4", []byte("batch2_value4"), version.NewHeight(6, 6)) // new key only in batch2
   159  	batch2.Delete("ns1", "key5", version.NewHeight(7, 7))                       // delete key only in batch2
   160  	batch2.Put("ns2", "key6", []byte("batch2_value6"), version.NewHeight(8, 8)) // namespace only in batch2
   161  
   162  	batch1.Merge(batch2)
   163  
   164  	// prepare final expected batch by writing all updates in the above order
   165  	expectedBatch := NewUpdateBatch()
   166  	expectedBatch.ContainsPostOrderWrites = true
   167  	expectedBatch.Put("ns1", "key1", []byte("batch1_value1"), version.NewHeight(1, 1))
   168  	expectedBatch.Put("ns1", "key2", []byte("batch1_value2"), version.NewHeight(2, 2))
   169  	expectedBatch.Put("ns1", "key3", []byte("batch1_value3"), version.NewHeight(3, 3))
   170  	expectedBatch.Put("ns1", "key1", []byte("batch2_value1"), version.NewHeight(4, 4))
   171  	expectedBatch.Delete("ns1", "key2", version.NewHeight(5, 5))
   172  	expectedBatch.Put("ns1", "key4", []byte("batch2_value4"), version.NewHeight(6, 6))
   173  	expectedBatch.Delete("ns1", "key5", version.NewHeight(7, 7))
   174  	expectedBatch.Put("ns2", "key6", []byte("batch2_value6"), version.NewHeight(8, 8))
   175  	require.Equal(t, expectedBatch, batch1)
   176  }