github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/fabric/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 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 require.Equal(t, expectedResults[i], res) 121 } 122 lastRes, err := itr.Next() 123 require.NoError(t, err) 124 require.Nil(t, lastRes) 125 itr.Close() 126 } 127 128 func TestMergeUpdateBatch(t *testing.T) { 129 batch1 := NewUpdateBatch() 130 batch1.Put("ns1", "key1", []byte("batch1_value1"), version.NewHeight(1, 1)) 131 batch1.Put("ns1", "key2", []byte("batch1_value2"), version.NewHeight(2, 2)) 132 batch1.Put("ns1", "key3", []byte("batch1_value3"), version.NewHeight(3, 3)) 133 134 batch2 := NewUpdateBatch() 135 batch2.ContainsPostOrderWrites = true 136 batch2.Put("ns1", "key1", []byte("batch2_value1"), version.NewHeight(4, 4)) // overwrite key1 with new value 137 batch2.Delete("ns1", "key2", version.NewHeight(5, 5)) // overwrite key2 with deletion 138 batch2.Put("ns1", "key4", []byte("batch2_value4"), version.NewHeight(6, 6)) // new key only in batch2 139 batch2.Delete("ns1", "key5", version.NewHeight(7, 7)) // delete key only in batch2 140 batch2.Put("ns2", "key6", []byte("batch2_value6"), version.NewHeight(8, 8)) // namespace only in batch2 141 142 batch1.Merge(batch2) 143 144 // prepare final expected batch by writing all updates in the above order 145 expectedBatch := NewUpdateBatch() 146 expectedBatch.ContainsPostOrderWrites = true 147 expectedBatch.Put("ns1", "key1", []byte("batch1_value1"), version.NewHeight(1, 1)) 148 expectedBatch.Put("ns1", "key2", []byte("batch1_value2"), version.NewHeight(2, 2)) 149 expectedBatch.Put("ns1", "key3", []byte("batch1_value3"), version.NewHeight(3, 3)) 150 expectedBatch.Put("ns1", "key1", []byte("batch2_value1"), version.NewHeight(4, 4)) 151 expectedBatch.Delete("ns1", "key2", version.NewHeight(5, 5)) 152 expectedBatch.Put("ns1", "key4", []byte("batch2_value4"), version.NewHeight(6, 6)) 153 expectedBatch.Delete("ns1", "key5", version.NewHeight(7, 7)) 154 expectedBatch.Put("ns2", "key6", []byte("batch2_value6"), version.NewHeight(8, 8)) 155 require.Equal(t, expectedBatch, batch1) 156 }