github.com/true-sqn/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 }