github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/statedb/commontests/test_common.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package commontests 8 9 import ( 10 "fmt" 11 "strings" 12 "testing" 13 14 "github.com/hechain20/hechain/core/ledger/internal/version" 15 "github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/statedb" 16 "github.com/stretchr/testify/require" 17 ) 18 19 // CheckDBsAfterDropFunc checks if the channel-specific dbs have been dropped 20 type CheckDBsAfterDropFunc func(channelName string) 21 22 // TestGetStateMultipleKeys tests read for given multiple keys 23 func TestGetStateMultipleKeys(t *testing.T, dbProvider statedb.VersionedDBProvider) { 24 db, err := dbProvider.GetDBHandle("testgetmultiplekeys", nil) 25 require.NoError(t, err) 26 27 // Test that savepoint is nil for a new state db 28 sp, err := db.GetLatestSavePoint() 29 require.NoError(t, err, "Error upon GetLatestSavePoint()") 30 require.Nil(t, sp) 31 32 batch := statedb.NewUpdateBatch() 33 expectedValues := make([]*statedb.VersionedValue, 2) 34 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 35 expectedValues[0] = &vv1 36 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 37 expectedValues[1] = &vv2 38 vv3 := statedb.VersionedValue{Value: []byte("value3"), Version: version.NewHeight(1, 3)} 39 vv4 := statedb.VersionedValue{Value: []byte{}, Version: version.NewHeight(1, 4)} 40 batch.Put("ns1", "key1", vv1.Value, vv1.Version) 41 batch.Put("ns1", "key2", vv2.Value, vv2.Version) 42 batch.Put("ns2", "key3", vv3.Value, vv3.Version) 43 batch.Put("ns2", "key4", vv4.Value, vv4.Version) 44 savePoint := version.NewHeight(2, 5) 45 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 46 47 actualValues, _ := db.GetStateMultipleKeys("ns1", []string{"key1", "key2"}) 48 require.Equal(t, expectedValues, actualValues) 49 } 50 51 // TestBasicRW tests basic read-write 52 func TestBasicRW(t *testing.T, dbProvider statedb.VersionedDBProvider) { 53 db, err := dbProvider.GetDBHandle("testbasicrw", nil) 54 require.NoError(t, err) 55 56 // Test that savepoint is nil for a new state db 57 sp, err := db.GetLatestSavePoint() 58 require.NoError(t, err, "Error upon GetLatestSavePoint()") 59 require.Nil(t, sp) 60 61 // Test retrieval of non-existent key - returns nil rather than error 62 // For more details see https://github.com/hyperledger-archives/fabric/issues/936. 63 val, err := db.GetState("ns", "key1") 64 require.NoError(t, err, "Should receive nil rather than error upon reading non existent key") 65 require.Nil(t, val) 66 67 batch := statedb.NewUpdateBatch() 68 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 69 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 70 vv3 := statedb.VersionedValue{Value: []byte("value3"), Version: version.NewHeight(1, 3)} 71 vv4 := statedb.VersionedValue{Value: []byte{}, Version: version.NewHeight(1, 4)} 72 vv5 := statedb.VersionedValue{Value: []byte("null"), Version: version.NewHeight(1, 5)} 73 batch.Put("ns1", "key1", vv1.Value, vv1.Version) 74 batch.Put("ns1", "key2", vv2.Value, vv2.Version) 75 batch.Put("ns2", "key3", vv3.Value, vv3.Version) 76 batch.Put("ns2", "key4", vv4.Value, vv4.Version) 77 batch.Put("ns2", "key5", vv5.Value, vv5.Version) 78 savePoint := version.NewHeight(2, 5) 79 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 80 81 vv, _ := db.GetState("ns1", "key1") 82 require.Equal(t, &vv1, vv) 83 84 vv, _ = db.GetState("ns2", "key4") 85 require.Equal(t, &vv4, vv) 86 87 vv, _ = db.GetState("ns2", "key5") 88 require.Equal(t, &vv5, vv) 89 90 sp, err = db.GetLatestSavePoint() 91 require.NoError(t, err) 92 require.Equal(t, savePoint, sp) 93 } 94 95 // TestDrop tests dropping channel-specific ledger data 96 func TestDrop(t *testing.T, dbProvider statedb.VersionedDBProvider, checkDBsAfterDropFunc CheckDBsAfterDropFunc) { 97 channel1 := "testdrop-channel-1" 98 channel2 := "testdrop-channel-2" 99 namespaces := map[string]string{ 100 channel1: "ns1", 101 channel2: "ns2", 102 } 103 104 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 105 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 106 107 for channelName, ns := range namespaces { 108 db, err := dbProvider.GetDBHandle(channelName, nil) 109 require.NoError(t, err) 110 111 batch := statedb.NewUpdateBatch() 112 batch.Put(ns, "key1", vv1.Value, vv1.Version) 113 batch.Put(ns, "key2", vv2.Value, vv2.Version) 114 savePoint := version.NewHeight(2, 2) 115 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 116 117 vv, err := db.GetState(ns, "key1") 118 require.NoError(t, err) 119 require.Equal(t, &vv1, vv) 120 vv, err = db.GetState(ns, "key2") 121 require.NoError(t, err) 122 require.Equal(t, &vv2, vv) 123 } 124 125 require.NoError(t, dbProvider.Drop(channel1)) 126 127 // verify channel1 data are dropped 128 checkDBsAfterDropFunc(channel1) 129 130 // verify channel2 data remain as is 131 db2, err := dbProvider.GetDBHandle(channel2, nil) 132 require.NoError(t, err) 133 134 vv, err := db2.GetState("ns2", "key1") 135 require.NoError(t, err) 136 require.Equal(t, &vv1, vv) 137 138 vv, err = db2.GetState("ns2", "key2") 139 require.NoError(t, err) 140 require.Equal(t, &vv2, vv) 141 142 // drop again should not fail 143 require.NoError(t, dbProvider.Drop(channel1)) 144 } 145 146 // TestMultiDBBasicRW tests basic read-write on multiple dbs 147 func TestMultiDBBasicRW(t *testing.T, dbProvider statedb.VersionedDBProvider) { 148 db1, err := dbProvider.GetDBHandle("testmultidbbasicrw", nil) 149 require.NoError(t, err) 150 151 db2, err := dbProvider.GetDBHandle("testmultidbbasicrw2", nil) 152 require.NoError(t, err) 153 154 batch1 := statedb.NewUpdateBatch() 155 vv1 := statedb.VersionedValue{Value: []byte("value1_db1"), Version: version.NewHeight(1, 1)} 156 vv2 := statedb.VersionedValue{Value: []byte("value2_db1"), Version: version.NewHeight(1, 2)} 157 batch1.Put("ns1", "key1", vv1.Value, vv1.Version) 158 batch1.Put("ns1", "key2", vv2.Value, vv2.Version) 159 savePoint1 := version.NewHeight(1, 2) 160 require.NoError(t, db1.ApplyUpdates(batch1, savePoint1)) 161 162 batch2 := statedb.NewUpdateBatch() 163 vv3 := statedb.VersionedValue{Value: []byte("value1_db2"), Version: version.NewHeight(1, 4)} 164 vv4 := statedb.VersionedValue{Value: []byte("value2_db2"), Version: version.NewHeight(1, 5)} 165 batch2.Put("ns1", "key1", vv3.Value, vv3.Version) 166 batch2.Put("ns1", "key2", vv4.Value, vv4.Version) 167 savePoint2 := version.NewHeight(1, 5) 168 require.NoError(t, db2.ApplyUpdates(batch2, savePoint2)) 169 170 vv, _ := db1.GetState("ns1", "key1") 171 require.Equal(t, &vv1, vv) 172 173 sp, err := db1.GetLatestSavePoint() 174 require.NoError(t, err) 175 require.Equal(t, savePoint1, sp) 176 177 vv, _ = db2.GetState("ns1", "key1") 178 require.Equal(t, &vv3, vv) 179 180 sp, err = db2.GetLatestSavePoint() 181 require.NoError(t, err) 182 require.Equal(t, savePoint2, sp) 183 } 184 185 // TestDeletes tests deletes 186 func TestDeletes(t *testing.T, dbProvider statedb.VersionedDBProvider) { 187 db, err := dbProvider.GetDBHandle("testdeletes", nil) 188 require.NoError(t, err) 189 190 batch := statedb.NewUpdateBatch() 191 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 192 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 193 vv3 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 3)} 194 vv4 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 4)} 195 196 batch.Put("ns", "key1", vv1.Value, vv1.Version) 197 batch.Put("ns", "key2", vv2.Value, vv2.Version) 198 batch.Put("ns", "key3", vv2.Value, vv3.Version) 199 batch.Put("ns", "key4", vv2.Value, vv4.Version) 200 batch.Delete("ns", "key3", version.NewHeight(1, 5)) 201 savePoint := version.NewHeight(1, 5) 202 err = db.ApplyUpdates(batch, savePoint) 203 require.NoError(t, err) 204 vv, _ := db.GetState("ns", "key2") 205 require.Equal(t, &vv2, vv) 206 207 vv, err = db.GetState("ns", "key3") 208 require.NoError(t, err) 209 require.Nil(t, vv) 210 211 batch = statedb.NewUpdateBatch() 212 batch.Delete("ns", "key2", version.NewHeight(1, 6)) 213 err = db.ApplyUpdates(batch, savePoint) 214 require.NoError(t, err) 215 vv, err = db.GetState("ns", "key2") 216 require.NoError(t, err) 217 require.Nil(t, vv) 218 } 219 220 // TestIterator tests the iterator 221 func TestIterator(t *testing.T, dbProvider statedb.VersionedDBProvider) { 222 db, err := dbProvider.GetDBHandle("testiterator", nil) 223 require.NoError(t, err) 224 require.NoError(t, db.Open()) 225 defer db.Close() 226 batch := statedb.NewUpdateBatch() 227 batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1)) 228 batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2)) 229 batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 3)) 230 batch.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 4)) 231 batch.Put("ns2", "key5", []byte("value5"), version.NewHeight(1, 5)) 232 batch.Put("ns2", "key6", []byte("value6"), version.NewHeight(1, 6)) 233 batch.Put("ns3", "key7", []byte("value7"), version.NewHeight(1, 7)) 234 savePoint := version.NewHeight(2, 5) 235 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 236 itr1, _ := db.GetStateRangeScanIterator("ns1", "key1", "") 237 testItr(t, itr1, []string{"key1", "key2", "key3", "key4"}) 238 239 itr2, _ := db.GetStateRangeScanIterator("ns1", "key2", "key3") 240 testItr(t, itr2, []string{"key2"}) 241 242 itr3, _ := db.GetStateRangeScanIterator("ns1", "", "") 243 testItr(t, itr3, []string{"key1", "key2", "key3", "key4"}) 244 245 itr4, _ := db.GetStateRangeScanIterator("ns2", "", "") 246 testItr(t, itr4, []string{"key5", "key6"}) 247 } 248 249 func testItr(t *testing.T, itr statedb.ResultsIterator, expectedKeys []string) { 250 defer itr.Close() 251 for _, expectedKey := range expectedKeys { 252 queryResult, err := itr.Next() 253 require.NoError(t, err) 254 require.Equal(t, expectedKey, queryResult.Key) 255 } 256 _, err := itr.Next() 257 require.NoError(t, err) 258 } 259 260 // TestQuery tests queries 261 func TestQuery(t *testing.T, dbProvider statedb.VersionedDBProvider) { 262 db, err := dbProvider.GetDBHandle("testquery", nil) 263 require.NoError(t, err) 264 require.NoError(t, db.Open()) 265 defer db.Close() 266 batch := statedb.NewUpdateBatch() 267 jsonValue1 := `{"asset_name": "marble1","color": "blue","size": 1,"owner": "tom"}` 268 batch.Put("ns1", "key1", []byte(jsonValue1), version.NewHeight(1, 1)) 269 jsonValue2 := `{"asset_name": "marble2","color": "blue","size": 2,"owner": "jerry"}` 270 batch.Put("ns1", "key2", []byte(jsonValue2), version.NewHeight(1, 2)) 271 jsonValue3 := `{"asset_name": "marble3","color": "blue","size": 3,"owner": "fred"}` 272 batch.Put("ns1", "key3", []byte(jsonValue3), version.NewHeight(1, 3)) 273 jsonValue4 := `{"asset_name": "marble4","color": "blue","size": 4,"owner": "martha"}` 274 batch.Put("ns1", "key4", []byte(jsonValue4), version.NewHeight(1, 4)) 275 jsonValue5 := `{"asset_name": "marble5","color": "blue","size": 5,"owner": "fred"}` 276 batch.Put("ns1", "key5", []byte(jsonValue5), version.NewHeight(1, 5)) 277 jsonValue6 := `{"asset_name": "marble6","color": "blue","size": 6,"owner": "elaine"}` 278 batch.Put("ns1", "key6", []byte(jsonValue6), version.NewHeight(1, 6)) 279 jsonValue7 := `{"asset_name": "marble7","color": "blue","size": 7,"owner": "fred"}` 280 batch.Put("ns1", "key7", []byte(jsonValue7), version.NewHeight(1, 7)) 281 jsonValue8 := `{"asset_name": "marble8","color": "blue","size": 8,"owner": "elaine"}` 282 batch.Put("ns1", "key8", []byte(jsonValue8), version.NewHeight(1, 8)) 283 jsonValue9 := `{"asset_name": "marble9","color": "green","size": 9,"owner": "fred"}` 284 batch.Put("ns1", "key9", []byte(jsonValue9), version.NewHeight(1, 9)) 285 jsonValue10 := `{"asset_name": "marble10","color": "green","size": 10,"owner": "mary"}` 286 batch.Put("ns1", "key10", []byte(jsonValue10), version.NewHeight(1, 10)) 287 jsonValue11 := `{"asset_name": "marble11","color": "cyan","size": 1000007,"owner": "joe"}` 288 batch.Put("ns1", "key11", []byte(jsonValue11), version.NewHeight(1, 11)) 289 290 // add keys for a separate namespace 291 batch.Put("ns2", "key1", []byte(jsonValue1), version.NewHeight(1, 12)) 292 batch.Put("ns2", "key2", []byte(jsonValue2), version.NewHeight(1, 13)) 293 batch.Put("ns2", "key3", []byte(jsonValue3), version.NewHeight(1, 14)) 294 batch.Put("ns2", "key4", []byte(jsonValue4), version.NewHeight(1, 15)) 295 batch.Put("ns2", "key5", []byte(jsonValue5), version.NewHeight(1, 16)) 296 batch.Put("ns2", "key6", []byte(jsonValue6), version.NewHeight(1, 17)) 297 batch.Put("ns2", "key7", []byte(jsonValue7), version.NewHeight(1, 18)) 298 batch.Put("ns2", "key8", []byte(jsonValue8), version.NewHeight(1, 19)) 299 batch.Put("ns2", "key9", []byte(jsonValue9), version.NewHeight(1, 20)) 300 batch.Put("ns2", "key10", []byte(jsonValue10), version.NewHeight(1, 21)) 301 302 savePoint := version.NewHeight(2, 22) 303 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 304 305 // query for owner=jerry, use namespace "ns1" 306 itr, err := db.ExecuteQuery("ns1", `{"selector":{"owner":"jerry"}}`) 307 require.NoError(t, err) 308 309 // verify one jerry result 310 queryResult1, err := itr.Next() 311 require.NoError(t, err) 312 require.NotNil(t, queryResult1) 313 314 stringRecord := string(queryResult1.Value) 315 bFoundRecord := strings.Contains(stringRecord, "jerry") 316 require.True(t, bFoundRecord) 317 318 // verify no more results 319 queryResult2, err := itr.Next() 320 require.NoError(t, err) 321 require.Nil(t, queryResult2) 322 323 // query for owner=jerry, use namespace "ns2" 324 itr, err = db.ExecuteQuery("ns2", `{"selector":{"owner":"jerry"}}`) 325 require.NoError(t, err) 326 327 // verify one jerry result 328 queryResult1, err = itr.Next() 329 require.NoError(t, err) 330 require.NotNil(t, queryResult1) 331 stringRecord = string(queryResult1.Value) 332 bFoundRecord = strings.Contains(stringRecord, "jerry") 333 require.True(t, bFoundRecord) 334 335 // verify no more results 336 queryResult2, err = itr.Next() 337 require.NoError(t, err) 338 require.Nil(t, queryResult2) 339 340 // query for owner=jerry, use namespace "ns3" 341 itr, err = db.ExecuteQuery("ns3", `{"selector":{"owner":"jerry"}}`) 342 require.NoError(t, err) 343 344 // verify results - should be no records 345 queryResult1, err = itr.Next() 346 require.NoError(t, err) 347 require.Nil(t, queryResult1) 348 349 // query using bad query string 350 _, err = db.ExecuteQuery("ns1", "this is an invalid query string") 351 require.Error(t, err, "Should have received an error for invalid query string") 352 353 // query returns 0 records 354 _, err = db.ExecuteQuery("ns1", `{"selector":{"owner":"not_a_valid_name"}}`) 355 require.NoError(t, err) 356 357 // verify no results 358 queryResult3, err := itr.Next() 359 require.NoError(t, err) 360 require.Nil(t, queryResult3) 361 362 // query with fields, namespace "ns1" 363 itr, err = db.ExecuteQuery("ns1", `{"selector":{"owner":"jerry"},"fields": ["owner", "asset_name", "color", "size"]}`) 364 require.NoError(t, err) 365 366 // verify one jerry result 367 queryResult1, err = itr.Next() 368 require.NoError(t, err) 369 require.NotNil(t, queryResult1) 370 stringRecord = string(queryResult1.Value) 371 bFoundRecord = strings.Contains(stringRecord, "jerry") 372 require.True(t, bFoundRecord) 373 374 // verify no more results 375 queryResult2, err = itr.Next() 376 require.NoError(t, err) 377 require.Nil(t, queryResult2) 378 379 // query with fields, namespace "ns2" 380 itr, err = db.ExecuteQuery("ns2", `{"selector":{"owner":"jerry"},"fields": ["owner", "asset_name", "color", "size"]}`) 381 require.NoError(t, err) 382 383 // verify one jerry result 384 queryResult1, err = itr.Next() 385 require.NoError(t, err) 386 require.NotNil(t, queryResult1) 387 stringRecord = string(queryResult1.Value) 388 bFoundRecord = strings.Contains(stringRecord, "jerry") 389 require.True(t, bFoundRecord) 390 391 // verify no more results 392 queryResult2, err = itr.Next() 393 require.NoError(t, err) 394 require.Nil(t, queryResult2) 395 396 // query with fields, namespace "ns3" 397 itr, err = db.ExecuteQuery("ns3", `{"selector":{"owner":"jerry"},"fields": ["owner", "asset_name", "color", "size"]}`) 398 require.NoError(t, err) 399 400 // verify no results 401 queryResult1, err = itr.Next() 402 require.NoError(t, err) 403 require.Nil(t, queryResult1) 404 405 // query with complex selector, namespace "ns1" 406 itr, err = db.ExecuteQuery("ns1", `{"selector":{"$and":[{"size":{"$gt": 5}},{"size":{"$lt":8}},{"$not":{"size":6}}]}}`) 407 require.NoError(t, err) 408 409 // verify one fred result 410 queryResult1, err = itr.Next() 411 require.NoError(t, err) 412 require.NotNil(t, queryResult1) 413 stringRecord = string(queryResult1.Value) 414 bFoundRecord = strings.Contains(stringRecord, "fred") 415 require.True(t, bFoundRecord) 416 417 // verify no more results 418 queryResult2, err = itr.Next() 419 require.NoError(t, err) 420 require.Nil(t, queryResult2) 421 422 // query with complex selector, namespace "ns2" 423 itr, err = db.ExecuteQuery("ns2", `{"selector":{"$and":[{"size":{"$gt": 5}},{"size":{"$lt":8}},{"$not":{"size":6}}]}}`) 424 require.NoError(t, err) 425 426 // verify one fred result 427 queryResult1, err = itr.Next() 428 require.NoError(t, err) 429 require.NotNil(t, queryResult1) 430 stringRecord = string(queryResult1.Value) 431 bFoundRecord = strings.Contains(stringRecord, "fred") 432 require.True(t, bFoundRecord) 433 434 // verify no more results 435 queryResult2, err = itr.Next() 436 require.NoError(t, err) 437 require.Nil(t, queryResult2) 438 439 // query with complex selector, namespace "ns3" 440 itr, err = db.ExecuteQuery("ns3", `{"selector":{"$and":[{"size":{"$gt": 5}},{"size":{"$lt":8}},{"$not":{"size":6}}]}}`) 441 require.NoError(t, err) 442 443 // verify no more results 444 queryResult1, err = itr.Next() 445 require.NoError(t, err) 446 require.Nil(t, queryResult1) 447 448 // query with embedded implicit "AND" and explicit "OR", namespace "ns1" 449 itr, err = db.ExecuteQuery("ns1", `{"selector":{"color":"green","$or":[{"owner":"fred"},{"owner":"mary"}]}}`) 450 require.NoError(t, err) 451 452 // verify one green result 453 queryResult1, err = itr.Next() 454 require.NoError(t, err) 455 require.NotNil(t, queryResult1) 456 stringRecord = string(queryResult1.Value) 457 bFoundRecord = strings.Contains(stringRecord, "green") 458 require.True(t, bFoundRecord) 459 460 // verify another green result 461 queryResult2, err = itr.Next() 462 require.NoError(t, err) 463 require.NotNil(t, queryResult2) 464 stringRecord = string(queryResult2.Value) 465 bFoundRecord = strings.Contains(stringRecord, "green") 466 require.True(t, bFoundRecord) 467 468 // verify no more results 469 queryResult3, err = itr.Next() 470 require.NoError(t, err) 471 require.Nil(t, queryResult3) 472 473 // query with embedded implicit "AND" and explicit "OR", namespace "ns2" 474 itr, err = db.ExecuteQuery("ns2", `{"selector":{"color":"green","$or":[{"owner":"fred"},{"owner":"mary"}]}}`) 475 require.NoError(t, err) 476 477 // verify one green result 478 queryResult1, err = itr.Next() 479 require.NoError(t, err) 480 require.NotNil(t, queryResult1) 481 stringRecord = string(queryResult1.Value) 482 bFoundRecord = strings.Contains(stringRecord, "green") 483 require.True(t, bFoundRecord) 484 485 // verify another green result 486 queryResult2, err = itr.Next() 487 require.NoError(t, err) 488 require.NotNil(t, queryResult2) 489 stringRecord = string(queryResult2.Value) 490 bFoundRecord = strings.Contains(stringRecord, "green") 491 require.True(t, bFoundRecord) 492 493 // verify no more results 494 queryResult3, err = itr.Next() 495 require.NoError(t, err) 496 require.Nil(t, queryResult3) 497 498 // query with embedded implicit "AND" and explicit "OR", namespace "ns3" 499 itr, err = db.ExecuteQuery("ns3", `{"selector":{"color":"green","$or":[{"owner":"fred"},{"owner":"mary"}]}}`) 500 require.NoError(t, err) 501 502 // verify no results 503 queryResult1, err = itr.Next() 504 require.NoError(t, err) 505 require.Nil(t, queryResult1) 506 507 // query with integer with digit-count equals 7 and response received is also received 508 // with same digit-count and there is no float transformation 509 itr, err = db.ExecuteQuery("ns1", `{"selector":{"$and":[{"size":{"$eq": 1000007}}]}}`) 510 require.NoError(t, err) 511 512 // verify one jerry result 513 queryResult1, err = itr.Next() 514 require.NoError(t, err) 515 require.NotNil(t, queryResult1) 516 stringRecord = string(queryResult1.Value) 517 bFoundRecord = strings.Contains(stringRecord, "joe") 518 require.True(t, bFoundRecord) 519 bFoundRecord = strings.Contains(stringRecord, "1000007") 520 require.True(t, bFoundRecord) 521 522 // verify no more results 523 queryResult2, err = itr.Next() 524 require.NoError(t, err) 525 require.Nil(t, queryResult2) 526 } 527 528 // TestGetVersion tests retrieving the version by namespace and key 529 func TestGetVersion(t *testing.T, dbProvider statedb.VersionedDBProvider) { 530 db, err := dbProvider.GetDBHandle("testgetversion", nil) 531 require.NoError(t, err) 532 533 batch := statedb.NewUpdateBatch() 534 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 535 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 536 vv3 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 3)} 537 vv4 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 4)} 538 539 batch.Put("ns", "key1", vv1.Value, vv1.Version) 540 batch.Put("ns", "key2", vv2.Value, vv2.Version) 541 batch.Put("ns", "key3", vv2.Value, vv3.Version) 542 batch.Put("ns", "key4", vv2.Value, vv4.Version) 543 savePoint := version.NewHeight(1, 5) 544 err = db.ApplyUpdates(batch, savePoint) 545 require.NoError(t, err) 546 547 // check to see if the bulk optimizable interface is supported (couchdb) 548 if bulkdb, ok := db.(statedb.BulkOptimizable); ok { 549 // clear the cached versions, this will force a read when getVerion is called 550 bulkdb.ClearCachedVersions() 551 } 552 553 // retrieve a version by namespace and key 554 resp, err := db.GetVersion("ns", "key2") 555 require.NoError(t, err) 556 require.Equal(t, version.NewHeight(1, 2), resp) 557 558 // attempt to retrieve an non-existent namespace and key 559 resp, err = db.GetVersion("ns2", "key2") 560 require.NoError(t, err) 561 require.Nil(t, resp) 562 563 // check to see if the bulk optimizable interface is supported (couchdb) 564 if bulkdb, ok := db.(statedb.BulkOptimizable); ok { 565 566 // clear the cached versions, this will force a read when getVerion is called 567 bulkdb.ClearCachedVersions() 568 569 // initialize a key list 570 loadKeys := []*statedb.CompositeKey{} 571 // create a composite key and add to the key list 572 compositeKey := statedb.CompositeKey{Namespace: "ns", Key: "key3"} 573 loadKeys = append(loadKeys, &compositeKey) 574 // load the committed versions 575 require.NoError(t, bulkdb.LoadCommittedVersions(loadKeys)) 576 577 // retrieve a version by namespace and key 578 resp, err := db.GetVersion("ns", "key3") 579 require.NoError(t, err) 580 require.Equal(t, version.NewHeight(1, 3), resp) 581 582 } 583 } 584 585 // TestSmallBatchSize tests multiple update batches 586 func TestSmallBatchSize(t *testing.T, dbProvider statedb.VersionedDBProvider) { 587 db, err := dbProvider.GetDBHandle("testsmallbatchsize", nil) 588 require.NoError(t, err) 589 require.NoError(t, db.Open()) 590 defer db.Close() 591 batch := statedb.NewUpdateBatch() 592 jsonValue1 := []byte(`{"asset_name": "marble1","color": "blue","size": 1,"owner": "tom"}`) 593 batch.Put("ns1", "key1", jsonValue1, version.NewHeight(1, 1)) 594 jsonValue2 := []byte(`{"asset_name": "marble2","color": "blue","size": 2,"owner": "jerry"}`) 595 batch.Put("ns1", "key2", jsonValue2, version.NewHeight(1, 2)) 596 jsonValue3 := []byte(`{"asset_name": "marble3","color": "blue","size": 3,"owner": "fred"}`) 597 batch.Put("ns1", "key3", jsonValue3, version.NewHeight(1, 3)) 598 jsonValue4 := []byte(`{"asset_name": "marble4","color": "blue","size": 4,"owner": "martha"}`) 599 batch.Put("ns1", "key4", jsonValue4, version.NewHeight(1, 4)) 600 jsonValue5 := []byte(`{"asset_name": "marble5","color": "blue","size": 5,"owner": "fred"}`) 601 batch.Put("ns1", "key5", jsonValue5, version.NewHeight(1, 5)) 602 jsonValue6 := []byte(`{"asset_name": "marble6","color": "blue","size": 6,"owner": "elaine"}`) 603 batch.Put("ns1", "key6", jsonValue6, version.NewHeight(1, 6)) 604 jsonValue7 := []byte(`{"asset_name": "marble7","color": "blue","size": 7,"owner": "fred"}`) 605 batch.Put("ns1", "key7", jsonValue7, version.NewHeight(1, 7)) 606 jsonValue8 := []byte(`{"asset_name": "marble8","color": "blue","size": 8,"owner": "elaine"}`) 607 batch.Put("ns1", "key8", jsonValue8, version.NewHeight(1, 8)) 608 jsonValue9 := []byte(`{"asset_name": "marble9","color": "green","size": 9,"owner": "fred"}`) 609 batch.Put("ns1", "key9", jsonValue9, version.NewHeight(1, 9)) 610 jsonValue10 := []byte(`{"asset_name": "marble10","color": "green","size": 10,"owner": "mary"}`) 611 batch.Put("ns1", "key10", jsonValue10, version.NewHeight(1, 10)) 612 jsonValue11 := []byte(`{"asset_name": "marble11","color": "cyan","size": 1000007,"owner": "joe"}`) 613 batch.Put("ns1", "key11", jsonValue11, version.NewHeight(1, 11)) 614 615 savePoint := version.NewHeight(1, 12) 616 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 617 618 // Verify all marbles were added 619 620 vv, _ := db.GetState("ns1", "key1") 621 require.JSONEq(t, string(jsonValue1), string(vv.Value)) 622 623 vv, _ = db.GetState("ns1", "key2") 624 require.JSONEq(t, string(jsonValue2), string(vv.Value)) 625 626 vv, _ = db.GetState("ns1", "key3") 627 require.JSONEq(t, string(jsonValue3), string(vv.Value)) 628 629 vv, _ = db.GetState("ns1", "key4") 630 require.JSONEq(t, string(jsonValue4), string(vv.Value)) 631 632 vv, _ = db.GetState("ns1", "key5") 633 require.JSONEq(t, string(jsonValue5), string(vv.Value)) 634 635 vv, _ = db.GetState("ns1", "key6") 636 require.JSONEq(t, string(jsonValue6), string(vv.Value)) 637 638 vv, _ = db.GetState("ns1", "key7") 639 require.JSONEq(t, string(jsonValue7), string(vv.Value)) 640 641 vv, _ = db.GetState("ns1", "key8") 642 require.JSONEq(t, string(jsonValue8), string(vv.Value)) 643 644 vv, _ = db.GetState("ns1", "key9") 645 require.JSONEq(t, string(jsonValue9), string(vv.Value)) 646 647 vv, _ = db.GetState("ns1", "key10") 648 require.JSONEq(t, string(jsonValue10), string(vv.Value)) 649 650 vv, _ = db.GetState("ns1", "key11") 651 require.JSONEq(t, string(jsonValue11), string(vv.Value)) 652 } 653 654 // TestBatchWithIndividualRetry tests a single failure in a batch 655 func TestBatchWithIndividualRetry(t *testing.T, dbProvider statedb.VersionedDBProvider) { 656 db, err := dbProvider.GetDBHandle("testbatchretry", nil) 657 require.NoError(t, err) 658 659 batch := statedb.NewUpdateBatch() 660 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 661 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 662 vv3 := statedb.VersionedValue{Value: []byte("value3"), Version: version.NewHeight(1, 3)} 663 vv4 := statedb.VersionedValue{Value: []byte("value4"), Version: version.NewHeight(1, 4)} 664 665 batch.Put("ns", "key1", vv1.Value, vv1.Version) 666 batch.Put("ns", "key2", vv2.Value, vv2.Version) 667 batch.Put("ns", "key3", vv3.Value, vv3.Version) 668 batch.Put("ns", "key4", vv4.Value, vv4.Version) 669 savePoint := version.NewHeight(1, 5) 670 err = db.ApplyUpdates(batch, savePoint) 671 require.NoError(t, err) 672 673 // Clear the cache for the next batch, in place of simulation 674 if bulkdb, ok := db.(statedb.BulkOptimizable); ok { 675 // clear the cached versions, this will force a read when getVerion is called 676 bulkdb.ClearCachedVersions() 677 } 678 679 batch = statedb.NewUpdateBatch() 680 batch.Put("ns", "key1", vv1.Value, vv1.Version) 681 batch.Put("ns", "key2", vv2.Value, vv2.Version) 682 batch.Put("ns", "key3", vv3.Value, vv3.Version) 683 batch.Put("ns", "key4", vv4.Value, vv4.Version) 684 savePoint = version.NewHeight(1, 6) 685 err = db.ApplyUpdates(batch, savePoint) 686 require.NoError(t, err) 687 688 // Update document key3 689 batch = statedb.NewUpdateBatch() 690 batch.Delete("ns", "key2", vv2.Version) 691 batch.Put("ns", "key3", vv3.Value, vv3.Version) 692 savePoint = version.NewHeight(1, 7) 693 err = db.ApplyUpdates(batch, savePoint) 694 require.NoError(t, err) 695 696 // This should force a retry for couchdb revision conflict for both delete and update 697 // Retry logic should correct the update and prevent delete from throwing an error 698 batch = statedb.NewUpdateBatch() 699 batch.Delete("ns", "key2", vv2.Version) 700 batch.Put("ns", "key3", vv3.Value, vv3.Version) 701 savePoint = version.NewHeight(1, 8) 702 err = db.ApplyUpdates(batch, savePoint) 703 require.NoError(t, err) 704 705 // Create a new set of values that use JSONs instead of binary 706 jsonValue5 := []byte(`{"asset_name": "marble5","color": "blue","size": 5,"owner": "fred"}`) 707 jsonValue6 := []byte(`{"asset_name": "marble6","color": "blue","size": 6,"owner": "elaine"}`) 708 jsonValue7 := []byte(`{"asset_name": "marble7","color": "blue","size": 7,"owner": "fred"}`) 709 jsonValue8 := []byte(`{"asset_name": "marble8","color": "blue","size": 8,"owner": "elaine"}`) 710 711 // Clear the cache for the next batch, in place of simulation 712 if bulkdb, ok := db.(statedb.BulkOptimizable); ok { 713 // clear the cached versions, this will force a read when getVersion is called 714 bulkdb.ClearCachedVersions() 715 } 716 717 batch = statedb.NewUpdateBatch() 718 batch.Put("ns1", "key5", jsonValue5, version.NewHeight(1, 9)) 719 batch.Put("ns1", "key6", jsonValue6, version.NewHeight(1, 10)) 720 batch.Put("ns1", "key7", jsonValue7, version.NewHeight(1, 11)) 721 batch.Put("ns1", "key8", jsonValue8, version.NewHeight(1, 12)) 722 savePoint = version.NewHeight(1, 6) 723 err = db.ApplyUpdates(batch, savePoint) 724 require.NoError(t, err) 725 726 // Clear the cache for the next batch, in place of simulation 727 if bulkdb, ok := db.(statedb.BulkOptimizable); ok { 728 // clear the cached versions, this will force a read when getVersion is called 729 bulkdb.ClearCachedVersions() 730 } 731 732 // Send the batch through again to test updates 733 batch = statedb.NewUpdateBatch() 734 batch.Put("ns1", "key5", jsonValue5, version.NewHeight(1, 9)) 735 batch.Put("ns1", "key6", jsonValue6, version.NewHeight(1, 10)) 736 batch.Put("ns1", "key7", jsonValue7, version.NewHeight(1, 11)) 737 batch.Put("ns1", "key8", jsonValue8, version.NewHeight(1, 12)) 738 savePoint = version.NewHeight(1, 6) 739 err = db.ApplyUpdates(batch, savePoint) 740 require.NoError(t, err) 741 742 // Update document key3 743 // this will cause an inconsistent cache entry for connection db2 744 batch = statedb.NewUpdateBatch() 745 batch.Delete("ns1", "key6", version.NewHeight(1, 13)) 746 batch.Put("ns1", "key7", jsonValue7, version.NewHeight(1, 14)) 747 savePoint = version.NewHeight(1, 15) 748 err = db.ApplyUpdates(batch, savePoint) 749 require.NoError(t, err) 750 751 // This should force a retry for couchdb revision conflict for both delete and update 752 // Retry logic should correct the update and prevent delete from throwing an error 753 batch = statedb.NewUpdateBatch() 754 batch.Delete("ns1", "key6", version.NewHeight(1, 16)) 755 batch.Put("ns1", "key7", jsonValue7, version.NewHeight(1, 17)) 756 savePoint = version.NewHeight(1, 18) 757 err = db.ApplyUpdates(batch, savePoint) 758 require.NoError(t, err) 759 } 760 761 // TestValueAndMetadataWrites tests statedb for value and metadata read-writes 762 func TestValueAndMetadataWrites(t *testing.T, dbProvider statedb.VersionedDBProvider) { 763 db, err := dbProvider.GetDBHandle("testvalueandmetadata", nil) 764 require.NoError(t, err) 765 batch := statedb.NewUpdateBatch() 766 767 vv1 := statedb.VersionedValue{Value: []byte("value1"), Metadata: []byte("metadata1"), Version: version.NewHeight(1, 1)} 768 vv2 := statedb.VersionedValue{Value: []byte("value2"), Metadata: []byte("metadata2"), Version: version.NewHeight(1, 2)} 769 vv3 := statedb.VersionedValue{Value: []byte("value3"), Version: version.NewHeight(1, 3)} 770 vv4 := statedb.VersionedValue{Value: []byte{}, Metadata: []byte("metadata4"), Version: version.NewHeight(1, 4)} 771 772 batch.PutValAndMetadata("ns1", "key1", vv1.Value, vv1.Metadata, vv1.Version) 773 batch.PutValAndMetadata("ns1", "key2", vv2.Value, vv2.Metadata, vv2.Version) 774 batch.PutValAndMetadata("ns2", "key3", vv3.Value, vv3.Metadata, vv3.Version) 775 batch.PutValAndMetadata("ns2", "key4", vv4.Value, vv4.Metadata, vv4.Version) 776 require.NoError(t, db.ApplyUpdates(batch, version.NewHeight(2, 5))) 777 778 vv, _ := db.GetState("ns1", "key1") 779 require.Equal(t, &vv1, vv) 780 781 vv, _ = db.GetState("ns1", "key2") 782 require.Equal(t, &vv2, vv) 783 784 vv, _ = db.GetState("ns2", "key3") 785 require.Equal(t, &vv3, vv) 786 787 vv, _ = db.GetState("ns2", "key4") 788 require.Equal(t, &vv4, vv) 789 } 790 791 // TestPaginatedRangeQuery tests range queries with pagination 792 func TestPaginatedRangeQuery(t *testing.T, dbProvider statedb.VersionedDBProvider) { 793 db, err := dbProvider.GetDBHandle("testpaginatedrangequery", nil) 794 require.NoError(t, err) 795 require.NoError(t, db.Open()) 796 defer db.Close() 797 batch := statedb.NewUpdateBatch() 798 jsonValue1 := `{"asset_name": "marble1","color": "blue","size": 1,"owner": "tom"}` 799 batch.Put("ns1", "key1", []byte(jsonValue1), version.NewHeight(1, 1)) 800 jsonValue2 := `{"asset_name": "marble2","color": "red","size": 2,"owner": "jerry"}` 801 batch.Put("ns1", "key2", []byte(jsonValue2), version.NewHeight(1, 2)) 802 jsonValue3 := `{"asset_name": "marble3","color": "red","size": 3,"owner": "fred"}` 803 batch.Put("ns1", "key3", []byte(jsonValue3), version.NewHeight(1, 3)) 804 jsonValue4 := `{"asset_name": "marble4","color": "red","size": 4,"owner": "martha"}` 805 batch.Put("ns1", "key4", []byte(jsonValue4), version.NewHeight(1, 4)) 806 jsonValue5 := `{"asset_name": "marble5","color": "blue","size": 5,"owner": "fred"}` 807 batch.Put("ns1", "key5", []byte(jsonValue5), version.NewHeight(1, 5)) 808 jsonValue6 := `{"asset_name": "marble6","color": "red","size": 6,"owner": "elaine"}` 809 batch.Put("ns1", "key6", []byte(jsonValue6), version.NewHeight(1, 6)) 810 jsonValue7 := `{"asset_name": "marble7","color": "blue","size": 7,"owner": "fred"}` 811 batch.Put("ns1", "key7", []byte(jsonValue7), version.NewHeight(1, 7)) 812 jsonValue8 := `{"asset_name": "marble8","color": "red","size": 8,"owner": "elaine"}` 813 batch.Put("ns1", "key8", []byte(jsonValue8), version.NewHeight(1, 8)) 814 jsonValue9 := `{"asset_name": "marble9","color": "green","size": 9,"owner": "fred"}` 815 batch.Put("ns1", "key9", []byte(jsonValue9), version.NewHeight(1, 9)) 816 jsonValue10 := `{"asset_name": "marble10","color": "green","size": 10,"owner": "mary"}` 817 batch.Put("ns1", "key10", []byte(jsonValue10), version.NewHeight(1, 10)) 818 819 jsonValue11 := `{"asset_name": "marble11","color": "cyan","size": 8,"owner": "joe"}` 820 batch.Put("ns1", "key11", []byte(jsonValue11), version.NewHeight(1, 11)) 821 jsonValue12 := `{"asset_name": "marble12","color": "red","size": 4,"owner": "martha"}` 822 batch.Put("ns1", "key12", []byte(jsonValue12), version.NewHeight(1, 4)) 823 jsonValue13 := `{"asset_name": "marble13","color": "red","size": 6,"owner": "james"}` 824 batch.Put("ns1", "key13", []byte(jsonValue13), version.NewHeight(1, 4)) 825 jsonValue14 := `{"asset_name": "marble14","color": "red","size": 10,"owner": "fred"}` 826 batch.Put("ns1", "key14", []byte(jsonValue14), version.NewHeight(1, 4)) 827 jsonValue15 := `{"asset_name": "marble15","color": "red","size": 8,"owner": "mary"}` 828 batch.Put("ns1", "key15", []byte(jsonValue15), version.NewHeight(1, 4)) 829 jsonValue16 := `{"asset_name": "marble16","color": "red","size": 4,"owner": "robert"}` 830 batch.Put("ns1", "key16", []byte(jsonValue16), version.NewHeight(1, 4)) 831 jsonValue17 := `{"asset_name": "marble17","color": "red","size": 2,"owner": "alan"}` 832 batch.Put("ns1", "key17", []byte(jsonValue17), version.NewHeight(1, 4)) 833 jsonValue18 := `{"asset_name": "marble18","color": "red","size": 10,"owner": "elaine"}` 834 batch.Put("ns1", "key18", []byte(jsonValue18), version.NewHeight(1, 4)) 835 jsonValue19 := `{"asset_name": "marble19","color": "red","size": 2,"owner": "alan"}` 836 batch.Put("ns1", "key19", []byte(jsonValue19), version.NewHeight(1, 4)) 837 jsonValue20 := `{"asset_name": "marble20","color": "red","size": 10,"owner": "elaine"}` 838 batch.Put("ns1", "key20", []byte(jsonValue20), version.NewHeight(1, 4)) 839 840 jsonValue21 := `{"asset_name": "marble21","color": "cyan","size": 1000007,"owner": "joe"}` 841 batch.Put("ns1", "key21", []byte(jsonValue21), version.NewHeight(1, 11)) 842 jsonValue22 := `{"asset_name": "marble22","color": "red","size": 4,"owner": "martha"}` 843 batch.Put("ns1", "key22", []byte(jsonValue22), version.NewHeight(1, 4)) 844 jsonValue23 := `{"asset_name": "marble23","color": "blue","size": 6,"owner": "james"}` 845 batch.Put("ns1", "key23", []byte(jsonValue23), version.NewHeight(1, 4)) 846 jsonValue24 := `{"asset_name": "marble24","color": "red","size": 10,"owner": "fred"}` 847 batch.Put("ns1", "key24", []byte(jsonValue24), version.NewHeight(1, 4)) 848 jsonValue25 := `{"asset_name": "marble25","color": "red","size": 8,"owner": "mary"}` 849 batch.Put("ns1", "key25", []byte(jsonValue25), version.NewHeight(1, 4)) 850 jsonValue26 := `{"asset_name": "marble26","color": "red","size": 4,"owner": "robert"}` 851 batch.Put("ns1", "key26", []byte(jsonValue26), version.NewHeight(1, 4)) 852 jsonValue27 := `{"asset_name": "marble27","color": "green","size": 2,"owner": "alan"}` 853 batch.Put("ns1", "key27", []byte(jsonValue27), version.NewHeight(1, 4)) 854 jsonValue28 := `{"asset_name": "marble28","color": "red","size": 10,"owner": "elaine"}` 855 batch.Put("ns1", "key28", []byte(jsonValue28), version.NewHeight(1, 4)) 856 jsonValue29 := `{"asset_name": "marble29","color": "red","size": 2,"owner": "alan"}` 857 batch.Put("ns1", "key29", []byte(jsonValue29), version.NewHeight(1, 4)) 858 jsonValue30 := `{"asset_name": "marble30","color": "red","size": 10,"owner": "elaine"}` 859 batch.Put("ns1", "key30", []byte(jsonValue30), version.NewHeight(1, 4)) 860 861 jsonValue31 := `{"asset_name": "marble31","color": "cyan","size": 1000007,"owner": "joe"}` 862 batch.Put("ns1", "key31", []byte(jsonValue31), version.NewHeight(1, 11)) 863 jsonValue32 := `{"asset_name": "marble32","color": "red","size": 4,"owner": "martha"}` 864 batch.Put("ns1", "key32", []byte(jsonValue32), version.NewHeight(1, 4)) 865 jsonValue33 := `{"asset_name": "marble33","color": "red","size": 6,"owner": "james"}` 866 batch.Put("ns1", "key33", []byte(jsonValue33), version.NewHeight(1, 4)) 867 jsonValue34 := `{"asset_name": "marble34","color": "red","size": 10,"owner": "fred"}` 868 batch.Put("ns1", "key34", []byte(jsonValue34), version.NewHeight(1, 4)) 869 jsonValue35 := `{"asset_name": "marble35","color": "red","size": 8,"owner": "mary"}` 870 batch.Put("ns1", "key35", []byte(jsonValue35), version.NewHeight(1, 4)) 871 jsonValue36 := `{"asset_name": "marble36","color": "orange","size": 4,"owner": "robert"}` 872 batch.Put("ns1", "key36", []byte(jsonValue36), version.NewHeight(1, 4)) 873 jsonValue37 := `{"asset_name": "marble37","color": "red","size": 2,"owner": "alan"}` 874 batch.Put("ns1", "key37", []byte(jsonValue37), version.NewHeight(1, 4)) 875 jsonValue38 := `{"asset_name": "marble38","color": "yellow","size": 10,"owner": "elaine"}` 876 batch.Put("ns1", "key38", []byte(jsonValue38), version.NewHeight(1, 4)) 877 jsonValue39 := `{"asset_name": "marble39","color": "red","size": 2,"owner": "alan"}` 878 batch.Put("ns1", "key39", []byte(jsonValue39), version.NewHeight(1, 4)) 879 jsonValue40 := `{"asset_name": "marble40","color": "red","size": 10,"owner": "elaine"}` 880 batch.Put("ns1", "key40", []byte(jsonValue40), version.NewHeight(1, 4)) 881 882 savePoint := version.NewHeight(2, 22) 883 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 884 885 // Test range query with no pagination 886 returnKeys := []string{} 887 _, err = executeRangeQuery(t, db, "ns1", "key1", "key15", int32(0), returnKeys) 888 require.NoError(t, err) 889 890 // Test range query with large page size (single page return) 891 returnKeys = []string{"key1", "key10", "key11", "key12", "key13", "key14"} 892 _, err = executeRangeQuery(t, db, "ns1", "key1", "key15", int32(10), returnKeys) 893 require.NoError(t, err) 894 895 // Test explicit pagination 896 // Test range query with multiple pages 897 returnKeys = []string{"key1", "key10"} 898 nextStartKey, err := executeRangeQuery(t, db, "ns1", "key1", "key22", int32(2), returnKeys) 899 require.NoError(t, err) 900 901 // NextStartKey is now passed in as startKey, verify the pagesize is working 902 returnKeys = []string{"key11", "key12"} 903 _, err = executeRangeQuery(t, db, "ns1", nextStartKey, "key22", int32(2), returnKeys) 904 require.NoError(t, err) 905 906 // Test implicit pagination 907 // Test range query with no pagesize and a small queryLimit 908 returnKeys = []string{} 909 _, err = executeRangeQuery(t, db, "ns1", "key1", "key15", int32(0), returnKeys) 910 require.NoError(t, err) 911 912 // Test range query with pagesize greater than the queryLimit 913 returnKeys = []string{"key1", "key10", "key11", "key12"} 914 _, err = executeRangeQuery(t, db, "ns1", "key1", "key15", int32(4), returnKeys) 915 require.NoError(t, err) 916 } 917 918 // TestRangeQuerySpecialCharacters tests range queries for keys with special characters and/or non-English characters 919 func TestRangeQuerySpecialCharacters(t *testing.T, dbProvider statedb.VersionedDBProvider) { 920 db, err := dbProvider.GetDBHandle("testrangequeryspecialcharacters", nil) 921 require.NoError(t, err) 922 require.NoError(t, db.Open()) 923 defer db.Close() 924 925 batch := statedb.NewUpdateBatch() 926 jsonValue1 := `{"asset_name": "marble1","color": "blue","size": 1,"owner": "tom"}` 927 batch.Put("ns1", "key1", []byte(jsonValue1), version.NewHeight(1, 1)) 928 jsonValue2 := `{"asset_name": "marble2","color": "red","size": 2,"owner": "jerry"}` 929 batch.Put("ns1", "key2", []byte(jsonValue2), version.NewHeight(1, 1)) 930 jsonValue3 := `{"asset_name": "marble3","color": "red","size": 2,"owner": "jerry"}` 931 batch.Put("ns1", "key1&%-", []byte(jsonValue3), version.NewHeight(1, 1)) 932 jsonValue4 := `{"asset_name": "marble4","color": "red","size": 4,"owner": "martha"}` 933 batch.Put("ns1", "key1-a", []byte(jsonValue4), version.NewHeight(1, 4)) 934 jsonValue5 := `{"asset_name": "marble5","color": "red","size": 2,"owner": "jerry"}` 935 batch.Put("ns1", "key1%=", []byte(jsonValue5), version.NewHeight(1, 2)) 936 jsonValue6 := `{"asset_name": "marble6","color": "red","size": 3,"owner": "fred"}` 937 batch.Put("ns1", "key1español", []byte(jsonValue6), version.NewHeight(1, 3)) 938 jsonValue7 := `{"asset_name": "marble7","color": "blue","size": 5,"owner": "fred"}` 939 batch.Put("ns1", "key1中文", []byte(jsonValue7), version.NewHeight(1, 5)) 940 jsonValue8 := `{"asset_name": "marble8","color": "blue","size": 7,"owner": "fred"}` 941 batch.Put("ns1", "key1한국어", []byte(jsonValue8), version.NewHeight(1, 7)) 942 jsonValue9 := `{"asset_name": "marble9","color": "blue","size": 5,"owner": "fred"}` 943 batch.Put("ns1", "中文key1", []byte(jsonValue9), version.NewHeight(1, 5)) 944 jsonValue10 := `{"asset_name": "marble10","color": "green","size": 10,"owner": "mary"}` 945 batch.Put("ns1", "key10", []byte(jsonValue10), version.NewHeight(1, 10)) 946 jsonValue11 := `{"asset_name": "marble11","color": "cyan","size": 8,"owner": "joe"}` 947 batch.Put("ns1", "key1z", []byte(jsonValue11), version.NewHeight(1, 11)) 948 949 savePoint := version.NewHeight(2, 22) 950 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 951 952 // Test range query for the keys with special or non-English characters 953 returnKeys := []string{"key1", "key1%=", "key1&%-", "key1-a", "key10", "key1español", "key1z", "key1中文", "key1한국어"} 954 // returnKeys := []string{"key1", "key1%=", "key1&%-", "key1-a", "key10", "key1español", "key1z"} 955 _, err = executeRangeQuery(t, db, "ns1", "key1", "key2", int32(10), returnKeys) 956 require.NoError(t, err) 957 } 958 959 func executeRangeQuery(t *testing.T, db statedb.VersionedDB, namespace, startKey, endKey string, pageSize int32, returnKeys []string) (string, error) { 960 var itr statedb.ResultsIterator 961 var err error 962 963 if pageSize == 0 { 964 itr, err = db.GetStateRangeScanIterator(namespace, startKey, endKey) 965 if err != nil { 966 return "", err 967 } 968 969 } else { 970 itr, err = db.GetStateRangeScanIteratorWithPagination(namespace, startKey, endKey, pageSize) 971 if err != nil { 972 return "", err 973 } 974 975 if pageSize > 0 { 976 TestItrWithoutClose(t, itr, returnKeys) 977 } 978 } 979 980 returnBookmark := "" 981 if pageSize > 0 { 982 if queryResultItr, ok := itr.(statedb.QueryResultsIterator); ok { 983 returnBookmark = queryResultItr.GetBookmarkAndClose() 984 } 985 } 986 return returnBookmark, nil 987 } 988 989 // TestItrWithoutClose verifies an iterator contains expected keys 990 func TestItrWithoutClose(t *testing.T, itr statedb.ResultsIterator, expectedKeys []string) { 991 for _, expectedKey := range expectedKeys { 992 queryResult, err := itr.Next() 993 require.NoError(t, err, "An unexpected error was thrown during iterator Next()") 994 require.Equal(t, expectedKey, queryResult.Key) 995 } 996 queryResult, err := itr.Next() 997 require.NoError(t, err, "An unexpected error was thrown during iterator Next()") 998 require.Nil(t, queryResult) 999 } 1000 1001 // TestApplyUpdatesWithNilHeight is a common test that is invoked by leveldb and couchdb for verifying that 1002 // the statedb commits the batch with a nil height (used for committing the missing private data for the old blocks) 1003 func TestApplyUpdatesWithNilHeight(t *testing.T, dbProvider statedb.VersionedDBProvider) { 1004 db, err := dbProvider.GetDBHandle("test-apply-updates-with-nil-height", nil) 1005 require.NoError(t, err) 1006 1007 batch1 := statedb.NewUpdateBatch() 1008 batch1.Put("ns", "key1", []byte("value1"), version.NewHeight(1, 4)) 1009 savePoint := version.NewHeight(1, 5) 1010 require.NoError(t, db.ApplyUpdates(batch1, savePoint)) 1011 1012 batch2 := statedb.NewUpdateBatch() 1013 batch2.Put("ns", "key1", []byte("value2"), version.NewHeight(1, 1)) 1014 require.NoError(t, db.ApplyUpdates(batch2, nil)) 1015 1016 ht, err := db.GetLatestSavePoint() 1017 require.NoError(t, err) 1018 require.Equal(t, savePoint, ht) // savepoint should still be what was set with batch1 1019 // (because batch2 calls ApplyUpdates with savepoint as nil) 1020 } 1021 1022 // TestDataExportImport is a common test that is invoked by leveldb and couchdb for testing the export and import of 1023 // statedb for snapshotting functionality 1024 func TestDataExportImport( 1025 t *testing.T, 1026 dbProvider statedb.VersionedDBProvider, 1027 ) { 1028 sourceDB, err := dbProvider.GetDBHandle("source_ledger", nil) 1029 require.NoError(t, err) 1030 1031 // generateSampleData returns a slice of KVs. The returned value contains five KVs for each of the namespaces 1032 generateSampleData := func(namespaces ...string) []*statedb.VersionedKV { 1033 sampleData := []*statedb.VersionedKV{} 1034 for _, ns := range namespaces { 1035 for i := 0; i < 6; i++ { 1036 sampleKV := &statedb.VersionedKV{ 1037 CompositeKey: &statedb.CompositeKey{ 1038 Namespace: ns, 1039 Key: fmt.Sprintf("key-%d", i), 1040 }, 1041 VersionedValue: &statedb.VersionedValue{ 1042 Version: version.NewHeight(1, 1), 1043 Metadata: []byte(fmt.Sprintf("metadata-for-key-%d-for-%s", i, ns)), 1044 }, 1045 } 1046 switch { 1047 case i < 3: 1048 binaryVal := fmt.Sprintf("value-for-key-%d-for-%s", i, ns) 1049 sampleKV.VersionedValue.Value = []byte(binaryVal) 1050 default: 1051 jsonVal := fmt.Sprintf(`{"color":"blue,"marble":"m%d", "namespace":"%s"}`, i, ns) 1052 sampleKV.VersionedValue.Value = []byte(jsonVal) 1053 } 1054 1055 sampleData = append(sampleData, sampleKV) 1056 } 1057 } 1058 return sampleData 1059 } 1060 1061 // add the sample data for five namespaces to the db 1062 allnamespaces := stringset{"", "ns1", "ns2", "ns3", "ns4"} 1063 batch := statedb.NewUpdateBatch() 1064 for _, kv := range generateSampleData(allnamespaces...) { 1065 batch.PutValAndMetadata(kv.Namespace, kv.Key, kv.Value, kv.Metadata, kv.Version) 1066 } 1067 require.NoError(t, sourceDB.ApplyUpdates(batch, version.NewHeight(5, 5))) 1068 1069 // verifyExportImport uses FullScanIterator (with skipping zero or more namespaces) 1070 // for exporting the data to import into another ledger instance and verifies the 1071 // correctness of the imported data 1072 verifyExportImport := func(destDBName string, skipNamespaces stringset) { 1073 fullScanItr, err := sourceDB.GetFullScanIterator( 1074 func(ns string) bool { 1075 return skipNamespaces.contains(ns) 1076 }, 1077 ) 1078 require.NoError(t, err) 1079 1080 err = dbProvider.ImportFromSnapshot(destDBName, version.NewHeight(10, 10), fullScanItr) 1081 require.NoError(t, err) 1082 1083 destinationDB, err := dbProvider.GetDBHandle(destDBName, nil) 1084 require.NoError(t, err) 1085 1086 fullScanItr, err = destinationDB.GetFullScanIterator( 1087 func(ns string) bool { 1088 return false 1089 }, 1090 ) 1091 require.NoError(t, err) 1092 1093 expectedNamespacesInDestinationDB := allnamespaces.minus(skipNamespaces) 1094 actualResults := []*statedb.VersionedKV{} 1095 for { 1096 kv, err := fullScanItr.Next() 1097 require.NoError(t, err) 1098 if kv == nil { 1099 break 1100 } 1101 vv, err := destinationDB.GetState(kv.Namespace, kv.Key) 1102 require.NoError(t, err) 1103 actualResults = append( 1104 actualResults, 1105 &statedb.VersionedKV{ 1106 CompositeKey: kv.CompositeKey, 1107 VersionedValue: vv, 1108 }, 1109 ) 1110 } 1111 1112 require.Equal(t, generateSampleData(expectedNamespacesInDestinationDB...), actualResults) 1113 retrievedSavepoint, err := destinationDB.GetLatestSavePoint() 1114 require.NoError(t, err) 1115 require.Equal(t, version.NewHeight(10, 10), retrievedSavepoint) 1116 } 1117 1118 testCases := []stringset{ 1119 {}, // skip no namespaces 1120 {"", "ns1", "ns2", "ns3", "ns4"}, // skip all the namespaces 1121 {""}, // skip the first namespace 1122 {"ns2"}, // skip the middle namespace 1123 {"ns4"}, // skip the last namespace 1124 {"", "ns1"}, // skip the first two namespaces 1125 {"ns3", "ns4"}, // skip the last two namespaces 1126 {"", "ns3"}, // skip two non-consequitive namespaces 1127 {"ns1", "ns4"}, // skip two non-consequitive namespaces 1128 {"", "ns4"}, // skip the first and last namespace 1129 } 1130 1131 for i, testCase := range testCases { 1132 name := fmt.Sprintf("test_case_%d", i) 1133 t.Run( 1134 name, 1135 func(t *testing.T) { 1136 verifyExportImport(name, testCase) 1137 }, 1138 ) 1139 } 1140 } 1141 1142 // CreateTestData creates test data for the given namespace and number of keys. 1143 func CreateTestData(t *testing.T, db statedb.VersionedDB, ns string, numKeys int) []string { 1144 batch := statedb.NewUpdateBatch() 1145 expectedKeys := make([]string, numKeys) 1146 for i := 0; i < numKeys; i++ { 1147 expectedKeys[i] = fmt.Sprintf("key%d", i) 1148 vv := statedb.VersionedValue{Value: []byte(fmt.Sprintf("value%d", i)), Version: version.NewHeight(1, uint64(i+1))} 1149 batch.Put(ns, expectedKeys[i], vv.Value, vv.Version) 1150 } 1151 savePoint := version.NewHeight(1, uint64(numKeys)) 1152 require.NoError(t, db.ApplyUpdates(batch, savePoint)) 1153 itr, _ := db.GetStateRangeScanIterator(ns, "", "") 1154 defer itr.Close() 1155 for _, expectedKey := range expectedKeys { 1156 queryResult, err := itr.Next() 1157 require.NoError(t, err) 1158 require.Equal(t, expectedKey, queryResult.Key) 1159 } 1160 return expectedKeys 1161 } 1162 1163 type stringset []string 1164 1165 func (s stringset) contains(str string) bool { 1166 for _, element := range s { 1167 if element == str { 1168 return true 1169 } 1170 } 1171 return false 1172 } 1173 1174 func (s stringset) minus(toMinus stringset) stringset { 1175 var final stringset 1176 for _, element := range s { 1177 if toMinus.contains(element) { 1178 continue 1179 } 1180 final = append(final, element) 1181 } 1182 return final 1183 }