github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/core/ledger/kvledger/txmgmt/statedb/commontests/test_common.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package commontests 18 19 import ( 20 "strings" 21 "testing" 22 23 "github.com/hyperledger/fabric/common/ledger/testutil" 24 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 25 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 26 ) 27 28 // TestBasicRW tests basic read-write 29 func TestBasicRW(t *testing.T, dbProvider statedb.VersionedDBProvider) { 30 db, err := dbProvider.GetDBHandle("testbasicrw") 31 testutil.AssertNoError(t, err, "") 32 33 // Test that savepoint is nil for a new state db 34 sp, err := db.GetLatestSavePoint() 35 testutil.AssertNoError(t, err, "Error upon GetLatestSavePoint()") 36 testutil.AssertNil(t, sp) 37 38 // Test retrieval of non-existent key - returns nil rather than error 39 // For more details see https://github.com/hyperledger-archives/fabric/issues/936. 40 val, err := db.GetState("ns", "key1") 41 testutil.AssertNoError(t, err, "Should receive nil rather than error upon reading non existent key") 42 testutil.AssertNil(t, val) 43 44 batch := statedb.NewUpdateBatch() 45 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 46 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 47 vv3 := statedb.VersionedValue{Value: []byte("value3"), Version: version.NewHeight(1, 3)} 48 vv4 := statedb.VersionedValue{Value: []byte{}, Version: version.NewHeight(1, 4)} 49 batch.Put("ns1", "key1", vv1.Value, vv1.Version) 50 batch.Put("ns1", "key2", vv2.Value, vv2.Version) 51 batch.Put("ns2", "key3", vv3.Value, vv3.Version) 52 batch.Put("ns2", "key4", vv4.Value, vv4.Version) 53 savePoint := version.NewHeight(2, 5) 54 db.ApplyUpdates(batch, savePoint) 55 56 vv, _ := db.GetState("ns1", "key1") 57 testutil.AssertEquals(t, vv, &vv1) 58 59 vv, _ = db.GetState("ns2", "key4") 60 testutil.AssertEquals(t, vv, &vv4) 61 62 sp, err = db.GetLatestSavePoint() 63 testutil.AssertNoError(t, err, "") 64 testutil.AssertEquals(t, sp, savePoint) 65 } 66 67 // TestMultiDBBasicRW tests basic read-write on multiple dbs 68 func TestMultiDBBasicRW(t *testing.T, dbProvider statedb.VersionedDBProvider) { 69 db1, err := dbProvider.GetDBHandle("testmultidbbasicrw") 70 testutil.AssertNoError(t, err, "") 71 72 db2, err := dbProvider.GetDBHandle("testmultidbbasicrw2") 73 testutil.AssertNoError(t, err, "") 74 75 batch1 := statedb.NewUpdateBatch() 76 vv1 := statedb.VersionedValue{Value: []byte("value1_db1"), Version: version.NewHeight(1, 1)} 77 vv2 := statedb.VersionedValue{Value: []byte("value2_db1"), Version: version.NewHeight(1, 2)} 78 batch1.Put("ns1", "key1", vv1.Value, vv1.Version) 79 batch1.Put("ns1", "key2", vv2.Value, vv2.Version) 80 savePoint1 := version.NewHeight(1, 2) 81 db1.ApplyUpdates(batch1, savePoint1) 82 83 batch2 := statedb.NewUpdateBatch() 84 vv3 := statedb.VersionedValue{Value: []byte("value1_db2"), Version: version.NewHeight(1, 4)} 85 vv4 := statedb.VersionedValue{Value: []byte("value2_db2"), Version: version.NewHeight(1, 5)} 86 batch2.Put("ns1", "key1", vv3.Value, vv3.Version) 87 batch2.Put("ns1", "key2", vv4.Value, vv4.Version) 88 savePoint2 := version.NewHeight(1, 5) 89 db2.ApplyUpdates(batch2, savePoint2) 90 91 vv, _ := db1.GetState("ns1", "key1") 92 testutil.AssertEquals(t, vv, &vv1) 93 94 sp, err := db1.GetLatestSavePoint() 95 testutil.AssertNoError(t, err, "") 96 testutil.AssertEquals(t, sp, savePoint1) 97 98 vv, _ = db2.GetState("ns1", "key1") 99 testutil.AssertEquals(t, vv, &vv3) 100 101 sp, err = db2.GetLatestSavePoint() 102 testutil.AssertNoError(t, err, "") 103 testutil.AssertEquals(t, sp, savePoint2) 104 } 105 106 // TestDeletes tests deteles 107 func TestDeletes(t *testing.T, dbProvider statedb.VersionedDBProvider) { 108 db, err := dbProvider.GetDBHandle("testdeletes") 109 testutil.AssertNoError(t, err, "") 110 111 batch := statedb.NewUpdateBatch() 112 vv1 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 1)} 113 vv2 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 2)} 114 vv3 := statedb.VersionedValue{Value: []byte("value1"), Version: version.NewHeight(1, 3)} 115 vv4 := statedb.VersionedValue{Value: []byte("value2"), Version: version.NewHeight(1, 4)} 116 117 batch.Put("ns", "key1", vv1.Value, vv1.Version) 118 batch.Put("ns", "key2", vv2.Value, vv2.Version) 119 batch.Put("ns", "key3", vv2.Value, vv3.Version) 120 batch.Put("ns", "key4", vv2.Value, vv4.Version) 121 batch.Delete("ns", "key3", version.NewHeight(1, 5)) 122 savePoint := version.NewHeight(1, 5) 123 err = db.ApplyUpdates(batch, savePoint) 124 testutil.AssertNoError(t, err, "") 125 vv, _ := db.GetState("ns", "key2") 126 testutil.AssertEquals(t, vv, &vv2) 127 128 vv, err = db.GetState("ns", "key3") 129 testutil.AssertNoError(t, err, "") 130 testutil.AssertNil(t, vv) 131 132 batch = statedb.NewUpdateBatch() 133 batch.Delete("ns", "key2", version.NewHeight(1, 6)) 134 err = db.ApplyUpdates(batch, savePoint) 135 testutil.AssertNoError(t, err, "") 136 vv, err = db.GetState("ns", "key2") 137 testutil.AssertNoError(t, err, "") 138 testutil.AssertNil(t, vv) 139 } 140 141 // TestIterator tests the iterator 142 func TestIterator(t *testing.T, dbProvider statedb.VersionedDBProvider) { 143 db, err := dbProvider.GetDBHandle("testiterator") 144 testutil.AssertNoError(t, err, "") 145 db.Open() 146 defer db.Close() 147 batch := statedb.NewUpdateBatch() 148 batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 1)) 149 batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 2)) 150 batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 3)) 151 batch.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 4)) 152 batch.Put("ns2", "key5", []byte("value5"), version.NewHeight(1, 5)) 153 batch.Put("ns2", "key6", []byte("value6"), version.NewHeight(1, 6)) 154 batch.Put("ns3", "key7", []byte("value7"), version.NewHeight(1, 7)) 155 savePoint := version.NewHeight(2, 5) 156 db.ApplyUpdates(batch, savePoint) 157 158 itr1, _ := db.GetStateRangeScanIterator("ns1", "key1", "") 159 testItr(t, itr1, []string{"key1", "key2", "key3", "key4"}) 160 161 itr2, _ := db.GetStateRangeScanIterator("ns1", "key2", "key3") 162 testItr(t, itr2, []string{"key2"}) 163 164 itr3, _ := db.GetStateRangeScanIterator("ns1", "", "") 165 testItr(t, itr3, []string{"key1", "key2", "key3", "key4"}) 166 167 itr4, _ := db.GetStateRangeScanIterator("ns2", "", "") 168 testItr(t, itr4, []string{"key5", "key6"}) 169 } 170 171 func testItr(t *testing.T, itr statedb.ResultsIterator, expectedKeys []string) { 172 defer itr.Close() 173 for _, expectedKey := range expectedKeys { 174 queryResult, _ := itr.Next() 175 vkv := queryResult.(*statedb.VersionedKV) 176 key := vkv.Key 177 testutil.AssertEquals(t, key, expectedKey) 178 } 179 last, err := itr.Next() 180 testutil.AssertNoError(t, err, "") 181 testutil.AssertNil(t, last) 182 } 183 184 // TestQuery tests queries 185 func TestQuery(t *testing.T, dbProvider statedb.VersionedDBProvider) { 186 db, err := dbProvider.GetDBHandle("testquery") 187 testutil.AssertNoError(t, err, "") 188 db.Open() 189 defer db.Close() 190 batch := statedb.NewUpdateBatch() 191 jsonValue1 := "{\"asset_name\": \"marble1\",\"color\": \"blue\",\"size\": 1,\"owner\": \"tom\"}" 192 batch.Put("ns1", "key1", []byte(jsonValue1), version.NewHeight(1, 1)) 193 jsonValue2 := "{\"asset_name\": \"marble2\",\"color\": \"blue\",\"size\": 2,\"owner\": \"jerry\"}" 194 batch.Put("ns1", "key2", []byte(jsonValue2), version.NewHeight(1, 2)) 195 jsonValue3 := "{\"asset_name\": \"marble3\",\"color\": \"blue\",\"size\": 3,\"owner\": \"fred\"}" 196 batch.Put("ns1", "key3", []byte(jsonValue3), version.NewHeight(1, 3)) 197 jsonValue4 := "{\"asset_name\": \"marble4\",\"color\": \"blue\",\"size\": 4,\"owner\": \"martha\"}" 198 batch.Put("ns1", "key4", []byte(jsonValue4), version.NewHeight(1, 4)) 199 jsonValue5 := "{\"asset_name\": \"marble5\",\"color\": \"blue\",\"size\": 5,\"owner\": \"fred\"}" 200 batch.Put("ns1", "key5", []byte(jsonValue5), version.NewHeight(1, 5)) 201 jsonValue6 := "{\"asset_name\": \"marble6\",\"color\": \"blue\",\"size\": 6,\"owner\": \"elaine\"}" 202 batch.Put("ns1", "key6", []byte(jsonValue6), version.NewHeight(1, 6)) 203 jsonValue7 := "{\"asset_name\": \"marble7\",\"color\": \"blue\",\"size\": 7,\"owner\": \"fred\"}" 204 batch.Put("ns1", "key7", []byte(jsonValue7), version.NewHeight(1, 7)) 205 jsonValue8 := "{\"asset_name\": \"marble8\",\"color\": \"blue\",\"size\": 8,\"owner\": \"elaine\"}" 206 batch.Put("ns1", "key8", []byte(jsonValue8), version.NewHeight(1, 8)) 207 jsonValue9 := "{\"asset_name\": \"marble9\",\"color\": \"green\",\"size\": 9,\"owner\": \"fred\"}" 208 batch.Put("ns1", "key9", []byte(jsonValue9), version.NewHeight(1, 9)) 209 jsonValue10 := "{\"asset_name\": \"marble10\",\"color\": \"green\",\"size\": 10,\"owner\": \"mary\"}" 210 batch.Put("ns1", "key10", []byte(jsonValue10), version.NewHeight(1, 10)) 211 jsonValue11 := "{\"asset_name\": \"marble11\",\"color\": \"cyan\",\"size\": 1000007,\"owner\": \"joe\"}" 212 batch.Put("ns1", "key11", []byte(jsonValue11), version.NewHeight(1, 11)) 213 214 //add keys for a separate namespace 215 batch.Put("ns2", "key1", []byte(jsonValue1), version.NewHeight(1, 12)) 216 batch.Put("ns2", "key2", []byte(jsonValue2), version.NewHeight(1, 13)) 217 batch.Put("ns2", "key3", []byte(jsonValue3), version.NewHeight(1, 14)) 218 batch.Put("ns2", "key4", []byte(jsonValue4), version.NewHeight(1, 15)) 219 batch.Put("ns2", "key5", []byte(jsonValue5), version.NewHeight(1, 16)) 220 batch.Put("ns2", "key6", []byte(jsonValue6), version.NewHeight(1, 17)) 221 batch.Put("ns2", "key7", []byte(jsonValue7), version.NewHeight(1, 18)) 222 batch.Put("ns2", "key8", []byte(jsonValue8), version.NewHeight(1, 19)) 223 batch.Put("ns2", "key9", []byte(jsonValue9), version.NewHeight(1, 20)) 224 batch.Put("ns2", "key10", []byte(jsonValue10), version.NewHeight(1, 21)) 225 226 savePoint := version.NewHeight(2, 22) 227 db.ApplyUpdates(batch, savePoint) 228 229 // query for owner=jerry, use namespace "ns1" 230 itr, err := db.ExecuteQuery("ns1", "{\"selector\":{\"owner\":\"jerry\"}}") 231 testutil.AssertNoError(t, err, "") 232 233 // verify one jerry result 234 queryResult1, err := itr.Next() 235 testutil.AssertNoError(t, err, "") 236 testutil.AssertNotNil(t, queryResult1) 237 versionedQueryRecord := queryResult1.(*statedb.VersionedKV) 238 stringRecord := string(versionedQueryRecord.Value) 239 bFoundRecord := strings.Contains(stringRecord, "jerry") 240 testutil.AssertEquals(t, bFoundRecord, true) 241 242 // verify no more results 243 queryResult2, err := itr.Next() 244 testutil.AssertNoError(t, err, "") 245 testutil.AssertNil(t, queryResult2) 246 247 // query for owner=jerry, use namespace "ns2" 248 itr, err = db.ExecuteQuery("ns2", "{\"selector\":{\"owner\":\"jerry\"}}") 249 testutil.AssertNoError(t, err, "") 250 251 // verify one jerry result 252 queryResult1, err = itr.Next() 253 testutil.AssertNoError(t, err, "") 254 testutil.AssertNotNil(t, queryResult1) 255 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 256 stringRecord = string(versionedQueryRecord.Value) 257 bFoundRecord = strings.Contains(stringRecord, "jerry") 258 testutil.AssertEquals(t, bFoundRecord, true) 259 260 // verify no more results 261 queryResult2, err = itr.Next() 262 testutil.AssertNoError(t, err, "") 263 testutil.AssertNil(t, queryResult2) 264 265 // query for owner=jerry, use namespace "ns3" 266 itr, err = db.ExecuteQuery("ns3", "{\"selector\":{\"owner\":\"jerry\"}}") 267 testutil.AssertNoError(t, err, "") 268 269 // verify results - should be no records 270 queryResult1, err = itr.Next() 271 testutil.AssertNoError(t, err, "") 272 testutil.AssertNil(t, queryResult1) 273 274 // query using bad query string 275 itr, err = db.ExecuteQuery("ns1", "this is an invalid query string") 276 testutil.AssertError(t, err, "Should have received an error for invalid query string") 277 278 // query returns 0 records 279 itr, err = db.ExecuteQuery("ns1", "{\"selector\":{\"owner\":\"not_a_valid_name\"}}") 280 testutil.AssertNoError(t, err, "") 281 282 // verify no results 283 queryResult3, err := itr.Next() 284 testutil.AssertNoError(t, err, "") 285 testutil.AssertNil(t, queryResult3) 286 287 // query with fields, namespace "ns1" 288 itr, err = db.ExecuteQuery("ns1", "{\"selector\":{\"owner\":\"jerry\"},\"fields\": [\"owner\", \"asset_name\", \"color\", \"size\"]}") 289 testutil.AssertNoError(t, err, "") 290 291 // verify one jerry result 292 queryResult1, err = itr.Next() 293 testutil.AssertNoError(t, err, "") 294 testutil.AssertNotNil(t, queryResult1) 295 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 296 stringRecord = string(versionedQueryRecord.Value) 297 bFoundRecord = strings.Contains(stringRecord, "jerry") 298 testutil.AssertEquals(t, bFoundRecord, true) 299 300 // verify no more results 301 queryResult2, err = itr.Next() 302 testutil.AssertNoError(t, err, "") 303 testutil.AssertNil(t, queryResult2) 304 305 // query with fields, namespace "ns2" 306 itr, err = db.ExecuteQuery("ns2", "{\"selector\":{\"owner\":\"jerry\"},\"fields\": [\"owner\", \"asset_name\", \"color\", \"size\"]}") 307 testutil.AssertNoError(t, err, "") 308 309 // verify one jerry result 310 queryResult1, err = itr.Next() 311 testutil.AssertNoError(t, err, "") 312 testutil.AssertNotNil(t, queryResult1) 313 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 314 stringRecord = string(versionedQueryRecord.Value) 315 bFoundRecord = strings.Contains(stringRecord, "jerry") 316 testutil.AssertEquals(t, bFoundRecord, true) 317 318 // verify no more results 319 queryResult2, err = itr.Next() 320 testutil.AssertNoError(t, err, "") 321 testutil.AssertNil(t, queryResult2) 322 323 // query with fields, namespace "ns3" 324 itr, err = db.ExecuteQuery("ns3", "{\"selector\":{\"owner\":\"jerry\"},\"fields\": [\"owner\", \"asset_name\", \"color\", \"size\"]}") 325 testutil.AssertNoError(t, err, "") 326 327 // verify no results 328 queryResult1, err = itr.Next() 329 testutil.AssertNoError(t, err, "") 330 testutil.AssertNil(t, queryResult1) 331 332 // query with complex selector, namespace "ns1" 333 itr, err = db.ExecuteQuery("ns1", "{\"selector\":{\"$and\":[{\"size\":{\"$gt\": 5}},{\"size\":{\"$lt\":8}},{\"$not\":{\"size\":6}}]}}") 334 testutil.AssertNoError(t, err, "") 335 336 // verify one fred result 337 queryResult1, err = itr.Next() 338 testutil.AssertNoError(t, err, "") 339 testutil.AssertNotNil(t, queryResult1) 340 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 341 stringRecord = string(versionedQueryRecord.Value) 342 bFoundRecord = strings.Contains(stringRecord, "fred") 343 testutil.AssertEquals(t, bFoundRecord, true) 344 345 // verify no more results 346 queryResult2, err = itr.Next() 347 testutil.AssertNoError(t, err, "") 348 testutil.AssertNil(t, queryResult2) 349 350 // query with complex selector, namespace "ns2" 351 itr, err = db.ExecuteQuery("ns2", "{\"selector\":{\"$and\":[{\"size\":{\"$gt\": 5}},{\"size\":{\"$lt\":8}},{\"$not\":{\"size\":6}}]}}") 352 testutil.AssertNoError(t, err, "") 353 354 // verify one fred result 355 queryResult1, err = itr.Next() 356 testutil.AssertNoError(t, err, "") 357 testutil.AssertNotNil(t, queryResult1) 358 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 359 stringRecord = string(versionedQueryRecord.Value) 360 bFoundRecord = strings.Contains(stringRecord, "fred") 361 testutil.AssertEquals(t, bFoundRecord, true) 362 363 // verify no more results 364 queryResult2, err = itr.Next() 365 testutil.AssertNoError(t, err, "") 366 testutil.AssertNil(t, queryResult2) 367 368 // query with complex selector, namespace "ns3" 369 itr, err = db.ExecuteQuery("ns3", "{\"selector\":{\"$and\":[{\"size\":{\"$gt\": 5}},{\"size\":{\"$lt\":8}},{\"$not\":{\"size\":6}}]}}") 370 testutil.AssertNoError(t, err, "") 371 372 // verify no more results 373 queryResult1, err = itr.Next() 374 testutil.AssertNoError(t, err, "") 375 testutil.AssertNil(t, queryResult1) 376 377 // query with embedded implicit "AND" and explicit "OR", namespace "ns1" 378 itr, err = db.ExecuteQuery("ns1", "{\"selector\":{\"color\":\"green\",\"$or\":[{\"owner\":\"fred\"},{\"owner\":\"mary\"}]}}") 379 testutil.AssertNoError(t, err, "") 380 381 // verify one green result 382 queryResult1, err = itr.Next() 383 testutil.AssertNoError(t, err, "") 384 testutil.AssertNotNil(t, queryResult1) 385 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 386 stringRecord = string(versionedQueryRecord.Value) 387 bFoundRecord = strings.Contains(stringRecord, "green") 388 testutil.AssertEquals(t, bFoundRecord, true) 389 390 // verify another green result 391 queryResult2, err = itr.Next() 392 testutil.AssertNoError(t, err, "") 393 testutil.AssertNotNil(t, queryResult2) 394 versionedQueryRecord = queryResult2.(*statedb.VersionedKV) 395 stringRecord = string(versionedQueryRecord.Value) 396 bFoundRecord = strings.Contains(stringRecord, "green") 397 testutil.AssertEquals(t, bFoundRecord, true) 398 399 // verify no more results 400 queryResult3, err = itr.Next() 401 testutil.AssertNoError(t, err, "") 402 testutil.AssertNil(t, queryResult3) 403 404 // query with embedded implicit "AND" and explicit "OR", namespace "ns2" 405 itr, err = db.ExecuteQuery("ns2", "{\"selector\":{\"color\":\"green\",\"$or\":[{\"owner\":\"fred\"},{\"owner\":\"mary\"}]}}") 406 testutil.AssertNoError(t, err, "") 407 408 // verify one green result 409 queryResult1, err = itr.Next() 410 testutil.AssertNoError(t, err, "") 411 testutil.AssertNotNil(t, queryResult1) 412 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 413 stringRecord = string(versionedQueryRecord.Value) 414 bFoundRecord = strings.Contains(stringRecord, "green") 415 testutil.AssertEquals(t, bFoundRecord, true) 416 417 // verify another green result 418 queryResult2, err = itr.Next() 419 testutil.AssertNoError(t, err, "") 420 testutil.AssertNotNil(t, queryResult2) 421 versionedQueryRecord = queryResult2.(*statedb.VersionedKV) 422 stringRecord = string(versionedQueryRecord.Value) 423 bFoundRecord = strings.Contains(stringRecord, "green") 424 testutil.AssertEquals(t, bFoundRecord, true) 425 426 // verify no more results 427 queryResult3, err = itr.Next() 428 testutil.AssertNoError(t, err, "") 429 testutil.AssertNil(t, queryResult3) 430 431 // query with embedded implicit "AND" and explicit "OR", namespace "ns3" 432 itr, err = db.ExecuteQuery("ns3", "{\"selector\":{\"color\":\"green\",\"$or\":[{\"owner\":\"fred\"},{\"owner\":\"mary\"}]}}") 433 testutil.AssertNoError(t, err, "") 434 435 // verify no results 436 queryResult1, err = itr.Next() 437 testutil.AssertNoError(t, err, "") 438 testutil.AssertNil(t, queryResult1) 439 440 // query with integer with digit-count equals 7 and response received is also received 441 // with same digit-count and there is no float transformation 442 itr, err = db.ExecuteQuery("ns1", "{\"selector\":{\"$and\":[{\"size\":{\"$eq\": 1000007}}]}}") 443 testutil.AssertNoError(t, err, "") 444 445 // verify one jerry result 446 queryResult1, err = itr.Next() 447 testutil.AssertNoError(t, err, "") 448 testutil.AssertNotNil(t, queryResult1) 449 versionedQueryRecord = queryResult1.(*statedb.VersionedKV) 450 stringRecord = string(versionedQueryRecord.Value) 451 bFoundRecord = strings.Contains(stringRecord, "joe") 452 testutil.AssertEquals(t, bFoundRecord, true) 453 bFoundRecord = strings.Contains(stringRecord, "1000007") 454 testutil.AssertEquals(t, bFoundRecord, true) 455 456 // verify no more results 457 queryResult2, err = itr.Next() 458 testutil.AssertNoError(t, err, "") 459 testutil.AssertNil(t, queryResult2) 460 461 }