github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/statedb/commontests/test_common.go (about)

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