github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/queryutil/combiner_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package queryutil_test 8 9 import ( 10 "errors" 11 "os" 12 "testing" 13 14 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate" 15 "github.com/hyperledger/fabric/core/ledger/util" 16 17 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 18 "github.com/hyperledger/fabric/common/flogging" 19 commonledger "github.com/hyperledger/fabric/common/ledger" 20 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/queryutil" 21 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/queryutil/mock" 22 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 23 statedbmock "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/mock" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestMain(m *testing.M) { 28 flogging.ActivateSpec("util,statedb=debug") 29 os.Exit(m.Run()) 30 } 31 32 func TestCombinerGetState(t *testing.T) { 33 batch1 := statedb.NewUpdateBatch() 34 batch1.Put("ns1", "key1", []byte("b1_value1"), nil) 35 batch1.Delete("ns1", "key2", nil) 36 batch1.Put("ns1", "key3", []byte("b1_value3"), nil) 37 38 batch2 := statedb.NewUpdateBatch() 39 batch2.Put("ns1", "key1", []byte("b2_value1"), nil) 40 batch2.Put("ns1", "key2", []byte("b2_value2"), nil) 41 batch2.Put("ns1", "key3", []byte("b2_value3"), nil) 42 43 batch3 := statedb.NewUpdateBatch() 44 batch3.Put("ns1", "key1", []byte("b3_value1"), nil) 45 batch3.Put("ns1", "key2", []byte("b3_value2"), nil) 46 batch3.Delete("ns1", "key3", nil) 47 48 combiner := &queryutil.QECombiner{ 49 QueryExecuters: []queryutil.QueryExecuter{ 50 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1}, 51 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2}, 52 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3}, 53 }} 54 55 val, err := combiner.GetState("ns1", "key1") 56 assert.NoError(t, err) 57 assert.Equal(t, []byte("b1_value1"), val) 58 59 val, err = combiner.GetState("ns1", "key2") 60 assert.NoError(t, err) 61 assert.Nil(t, val) 62 63 val, err = combiner.GetState("ns1", "key3") 64 assert.NoError(t, err) 65 assert.Equal(t, []byte("b1_value3"), val) 66 67 combiner = &queryutil.QECombiner{ 68 QueryExecuters: []queryutil.QueryExecuter{ 69 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3}, 70 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2}, 71 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1}, 72 }} 73 val, err = combiner.GetState("ns1", "key1") 74 assert.NoError(t, err) 75 assert.Equal(t, []byte("b3_value1"), val) 76 77 val, err = combiner.GetState("ns1", "key2") 78 assert.NoError(t, err) 79 assert.Equal(t, []byte("b3_value2"), val) 80 81 val, err = combiner.GetState("ns1", "key3") 82 assert.NoError(t, err) 83 assert.Nil(t, val) 84 } 85 86 func TestCombinerRangeScan(t *testing.T) { 87 batch1 := statedb.NewUpdateBatch() 88 batch1.Put("ns1", "key1", []byte("batch1_value1"), nil) 89 batch1.Delete("ns1", "key2", nil) 90 batch1.Put("ns1", "key3", []byte("batch1_value3"), nil) 91 92 batch2 := statedb.NewUpdateBatch() 93 batch2.Put("ns1", "key1", []byte("batch2_value1"), nil) 94 batch2.Put("ns1", "key2", []byte("batch2_value2"), nil) 95 batch2.Delete("ns1", "key3", nil) 96 batch2.Put("ns1", "key4", []byte("batch2_value4"), nil) 97 98 batch3 := statedb.NewUpdateBatch() 99 batch3.Put("ns1", "key0", []byte("batch3_value0"), nil) 100 batch3.Put("ns1", "key1", []byte("batch3_value1"), nil) 101 batch3.Put("ns1", "key2", []byte("batch3_value2"), nil) 102 batch3.Put("ns1", "key3", []byte("batch3_value3"), nil) 103 batch3.Put("ns1", "key4", []byte("batch3_value4"), nil) 104 batch3.Put("ns1", "key5", []byte("batch3_value5"), nil) 105 106 combiner := &queryutil.QECombiner{ 107 QueryExecuters: []queryutil.QueryExecuter{ 108 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1}, 109 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2}, 110 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3}, 111 }, 112 } 113 114 itr, err := combiner.GetStateRangeScanIterator("ns1", "key1", "key4") 115 assert.NoError(t, err) 116 expectedResults := []*queryresult.KV{ 117 {Namespace: "ns1", Key: "key1", Value: []byte("batch1_value1")}, 118 {Namespace: "ns1", Key: "key3", Value: []byte("batch1_value3")}, 119 } 120 testutilCheckIteratorResults(t, itr, expectedResults) 121 122 itr, err = combiner.GetStateRangeScanIterator("ns1", "key0", "key6") 123 assert.NoError(t, err) 124 expectedResults = []*queryresult.KV{ 125 {Namespace: "ns1", Key: "key0", Value: []byte("batch3_value0")}, 126 {Namespace: "ns1", Key: "key1", Value: []byte("batch1_value1")}, 127 {Namespace: "ns1", Key: "key3", Value: []byte("batch1_value3")}, 128 {Namespace: "ns1", Key: "key4", Value: []byte("batch2_value4")}, 129 {Namespace: "ns1", Key: "key5", Value: []byte("batch3_value5")}, 130 } 131 testutilCheckIteratorResults(t, itr, expectedResults) 132 133 combiner = &queryutil.QECombiner{ 134 QueryExecuters: []queryutil.QueryExecuter{ 135 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch3}, 136 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch2}, 137 &queryutil.UpdateBatchBackedQueryExecuter{UpdateBatch: batch1}, 138 }, 139 } 140 itr, err = combiner.GetStateRangeScanIterator("ns1", "key0", "key6") 141 assert.NoError(t, err) 142 expectedResults = []*queryresult.KV{ 143 {Namespace: "ns1", Key: "key0", Value: []byte("batch3_value0")}, 144 {Namespace: "ns1", Key: "key1", Value: []byte("batch3_value1")}, 145 {Namespace: "ns1", Key: "key2", Value: []byte("batch3_value2")}, 146 {Namespace: "ns1", Key: "key3", Value: []byte("batch3_value3")}, 147 {Namespace: "ns1", Key: "key4", Value: []byte("batch3_value4")}, 148 {Namespace: "ns1", Key: "key5", Value: []byte("batch3_value5")}, 149 } 150 testutilCheckIteratorResults(t, itr, expectedResults) 151 } 152 153 func TestGetStateError(t *testing.T) { 154 qe1 := &mock.QueryExecuter{} 155 qe1.GetStateReturns(&statedb.VersionedValue{Value: []byte("testValue")}, nil) 156 qe2 := &mock.QueryExecuter{} 157 qe2.GetStateReturns(nil, errors.New("Error for testing")) 158 combiner1 := &queryutil.QECombiner{ 159 QueryExecuters: []queryutil.QueryExecuter{ 160 qe1, qe2, 161 }, 162 } 163 _, err := combiner1.GetState("ns", "key1") 164 assert.NoError(t, err) 165 166 combiner2 := &queryutil.QECombiner{ 167 QueryExecuters: []queryutil.QueryExecuter{ 168 qe2, qe1, 169 }, 170 } 171 _, err = combiner2.GetState("ns", "key1") 172 assert.Error(t, err) 173 } 174 175 func TestGetRangeScanError(t *testing.T) { 176 itr1 := &statedbmock.ResultsIterator{} 177 itr1.NextReturns( 178 &statedb.VersionedKV{ 179 CompositeKey: statedb.CompositeKey{Namespace: "ns", Key: "dummyKey"}, 180 VersionedValue: statedb.VersionedValue{Value: []byte("dummyVal")}, 181 }, 182 nil, 183 ) 184 185 qe1 := &mock.QueryExecuter{} 186 qe1.GetStateRangeScanIteratorReturns(itr1, nil) 187 qe2 := &mock.QueryExecuter{} 188 qe2.GetStateRangeScanIteratorReturns(nil, errors.New("dummy error on getting the iterator")) 189 combiner := &queryutil.QECombiner{ 190 QueryExecuters: []queryutil.QueryExecuter{ 191 qe1, qe2, 192 }, 193 } 194 _, err := combiner.GetStateRangeScanIterator("ns", "startKey", "endKey") 195 assert.Error(t, err) 196 } 197 198 func TestGetRangeScanUnderlyingIteratorReturnsError(t *testing.T) { 199 itr1 := &statedbmock.ResultsIterator{} 200 itr1.NextReturns( 201 &statedb.VersionedKV{ 202 CompositeKey: statedb.CompositeKey{Namespace: "ns", Key: "dummyKey"}, 203 VersionedValue: statedb.VersionedValue{Value: []byte("dummyVal")}, 204 }, 205 nil, 206 ) 207 208 itr2 := &statedbmock.ResultsIterator{} 209 itr2.NextReturns( 210 nil, 211 errors.New("dummyErrorOnIteratorNext"), 212 ) 213 214 qe1 := &mock.QueryExecuter{} 215 qe1.GetStateRangeScanIteratorReturns(itr1, nil) 216 qe2 := &mock.QueryExecuter{} 217 qe2.GetStateRangeScanIteratorReturns(itr2, nil) 218 combiner := &queryutil.QECombiner{ 219 QueryExecuters: []queryutil.QueryExecuter{ 220 qe1, qe2, 221 }, 222 } 223 _, err := combiner.GetStateRangeScanIterator("ns", "startKey", "endKey") 224 assert.Error(t, err) 225 } 226 227 func TestGetPrivateDataHash(t *testing.T) { 228 batch1 := privacyenabledstate.NewHashedUpdateBatch() 229 key1Hash := util.ComputeStringHash("key1") 230 key2Hash := util.ComputeStringHash("key2") 231 key3Hash := util.ComputeStringHash("key3") 232 233 batch1.Put("ns1", "coll1", key1Hash, []byte("b1_value1"), nil) 234 batch1.Delete("ns1", "coll1", key2Hash, nil) 235 batch1.Put("ns1", "coll1", key3Hash, []byte("b1_value3"), nil) 236 237 batch2 := privacyenabledstate.NewHashedUpdateBatch() 238 batch2.Put("ns1", "coll1", key1Hash, []byte("b2_value1"), nil) 239 batch2.Put("ns1", "coll1", key2Hash, []byte("b2_value2"), nil) 240 batch2.Put("ns1", "coll1", key3Hash, []byte("b2_value3"), nil) 241 242 batch3 := privacyenabledstate.NewHashedUpdateBatch() 243 batch3.Put("ns1", "coll1", key1Hash, []byte("b3_value1"), nil) 244 batch3.Put("ns1", "coll1", key2Hash, []byte("b3_value2"), nil) 245 246 combiner := &queryutil.QECombiner{ 247 QueryExecuters: []queryutil.QueryExecuter{ 248 &queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch1}, 249 &queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch2}, 250 &queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch3}, 251 }} 252 253 val, err := combiner.GetPrivateDataHash("ns1", "coll1", "key1") 254 assert.NoError(t, err) 255 assert.Equal(t, []byte("b1_value1"), val) 256 257 val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key2") 258 assert.NoError(t, err) 259 assert.Nil(t, val) 260 261 val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key3") 262 assert.NoError(t, err) 263 assert.Equal(t, []byte("b1_value3"), val) 264 265 combiner = &queryutil.QECombiner{ 266 QueryExecuters: []queryutil.QueryExecuter{ 267 &queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch3}, 268 &queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch2}, 269 &queryutil.UpdateBatchBackedQueryExecuter{HashUpdatesBatch: batch1}, 270 }} 271 val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key1") 272 assert.NoError(t, err) 273 assert.Equal(t, []byte("b3_value1"), val) 274 275 val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key2") 276 assert.NoError(t, err) 277 assert.Equal(t, []byte("b3_value2"), val) 278 279 val, err = combiner.GetPrivateDataHash("ns1", "coll1", "key3") 280 assert.NoError(t, err) 281 assert.Equal(t, []byte("b2_value3"), val) 282 } 283 284 func TestGetPrivateDataHashError(t *testing.T) { 285 qe1 := &mock.QueryExecuter{} 286 qe1.GetPrivateDataHashReturns(&statedb.VersionedValue{Value: []byte("testValue")}, nil) 287 qe2 := &mock.QueryExecuter{} 288 qe2.GetPrivateDataHashReturns(nil, errors.New("Error for testing")) 289 combiner1 := &queryutil.QECombiner{ 290 QueryExecuters: []queryutil.QueryExecuter{ 291 qe1, qe2, 292 }, 293 } 294 _, err := combiner1.GetPrivateDataHash("ns", "coll1", "key1") 295 assert.NoError(t, err) 296 297 combiner2 := &queryutil.QECombiner{ 298 QueryExecuters: []queryutil.QueryExecuter{ 299 qe2, qe1, 300 }, 301 } 302 _, err = combiner2.GetPrivateDataHash("ns", "coll1", "key1") 303 assert.Error(t, err) 304 } 305 306 func testutilCheckIteratorResults(t *testing.T, itr commonledger.ResultsIterator, expectedResults []*queryresult.KV) { 307 results := []*queryresult.KV{} 308 for { 309 result, err := itr.Next() 310 assert.NoError(t, err) 311 if result == nil { 312 break 313 } 314 results = append(results, result.(*queryresult.KV)) 315 } 316 assert.Equal(t, expectedResults, results) 317 }