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  }