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