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 }