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