github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/util/leveldbhelper/leveldb_provider_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package leveldbhelper
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"testing"
    13  
    14  	"github.com/hechain20/hechain/common/ledger/dataformat"
    15  
    16  	"github.com/hechain20/hechain/common/flogging"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestMain(m *testing.M) {
    21  	flogging.ActivateSpec("leveldbhelper=debug")
    22  	os.Exit(m.Run())
    23  }
    24  
    25  func TestDBBasicWriteAndReads(t *testing.T) {
    26  	testDBBasicWriteAndReads(t, "db1", "db2", "")
    27  }
    28  
    29  func TestIterator(t *testing.T) {
    30  	env := newTestProviderEnv(t, testDBPath)
    31  	defer env.cleanup()
    32  	p := env.provider
    33  
    34  	db1 := p.GetDBHandle("db1")
    35  	db2 := p.GetDBHandle("db2")
    36  	db3 := p.GetDBHandle("db3")
    37  	for i := 0; i < 20; i++ {
    38  		db1.Put([]byte(createTestKey(i)), []byte(createTestValue("db1", i)), false)
    39  		db2.Put([]byte(createTestKey(i)), []byte(createTestValue("db2", i)), false)
    40  		db3.Put([]byte(createTestKey(i)), []byte(createTestValue("db3", i)), false)
    41  	}
    42  
    43  	rangeTestCases := []struct {
    44  		startKey       []byte
    45  		endKey         []byte
    46  		expectedKeys   []string
    47  		expectedValues []string
    48  	}{
    49  		{
    50  			startKey:       []byte(createTestKey(2)),
    51  			endKey:         []byte(createTestKey(4)),
    52  			expectedKeys:   createTestKeys(2, 3),
    53  			expectedValues: createTestValues("db2", 2, 3),
    54  		},
    55  		{
    56  			startKey:       []byte(createTestKey(2)),
    57  			endKey:         nil,
    58  			expectedKeys:   createTestKeys(2, 19),
    59  			expectedValues: createTestValues("db2", 2, 19),
    60  		},
    61  		{
    62  			startKey:       nil,
    63  			endKey:         nil,
    64  			expectedKeys:   createTestKeys(0, 19),
    65  			expectedValues: createTestValues("db2", 0, 19),
    66  		},
    67  	}
    68  
    69  	for i, testCase := range rangeTestCases {
    70  		t.Run(
    71  			fmt.Sprintf("range testCase %d", i),
    72  			func(t *testing.T) {
    73  				itr, err := db2.GetIterator(testCase.startKey, testCase.endKey)
    74  				require.NoError(t, err)
    75  				defer itr.Release()
    76  				checkItrResults(t, itr, testCase.expectedKeys, testCase.expectedValues)
    77  			},
    78  		)
    79  	}
    80  
    81  	rangeWithSeekTestCases := []struct {
    82  		startKey          []byte
    83  		endKey            []byte
    84  		seekToKey         []byte
    85  		itrAtKeyAfterSeek []byte
    86  		expectedKeys      []string
    87  		expectedValues    []string
    88  	}{
    89  		{
    90  			startKey:          nil,
    91  			endKey:            nil,
    92  			seekToKey:         []byte(createTestKey(10)),
    93  			itrAtKeyAfterSeek: []byte(createTestKey(10)),
    94  			expectedKeys:      createTestKeys(11, 19),
    95  			expectedValues:    createTestValues("db1", 11, 19),
    96  		},
    97  		{
    98  			startKey:          []byte(createTestKey(11)),
    99  			endKey:            nil,
   100  			seekToKey:         []byte(createTestKey(5)),
   101  			itrAtKeyAfterSeek: []byte(createTestKey(11)),
   102  			expectedKeys:      createTestKeys(12, 19),
   103  			expectedValues:    createTestValues("db1", 12, 19),
   104  		},
   105  		{
   106  			startKey:          nil,
   107  			endKey:            nil,
   108  			seekToKey:         []byte(createTestKey(19)),
   109  			itrAtKeyAfterSeek: []byte(createTestKey(19)),
   110  			expectedKeys:      nil,
   111  			expectedValues:    nil,
   112  		},
   113  	}
   114  
   115  	for i, testCase := range rangeWithSeekTestCases {
   116  		t.Run(
   117  			fmt.Sprintf("range with seek testCase %d", i),
   118  			func(t *testing.T) {
   119  				itr, err := db1.GetIterator(testCase.startKey, testCase.endKey)
   120  				require.NoError(t, err)
   121  				defer itr.Release()
   122  				require.True(t, itr.Seek(testCase.seekToKey))
   123  				require.Equal(t, testCase.itrAtKeyAfterSeek, itr.Key())
   124  				checkItrResults(t, itr, testCase.expectedKeys, testCase.expectedValues)
   125  			},
   126  		)
   127  	}
   128  
   129  	t.Run("test-first-prev", func(t *testing.T) {
   130  		itr, err := db1.GetIterator(nil, nil)
   131  		require.NoError(t, err)
   132  		defer itr.Release()
   133  		require.True(t, itr.Seek([]byte(createTestKey(10))))
   134  		require.Equal(t, []byte(createTestKey(10)), itr.Key())
   135  		checkItrResults(t, itr, createTestKeys(11, 19), createTestValues("db1", 11, 19))
   136  
   137  		require.True(t, itr.First())
   138  		require.True(t, itr.Seek([]byte(createTestKey(10))))
   139  		require.Equal(t, []byte(createTestKey(10)), itr.Key())
   140  		require.True(t, itr.Prev())
   141  		checkItrResults(t, itr, createTestKeys(10, 19), createTestValues("db1", 10, 19))
   142  
   143  		require.True(t, itr.First())
   144  		require.False(t, itr.Seek([]byte(createTestKey(20))))
   145  		require.True(t, itr.First())
   146  		checkItrResults(t, itr, createTestKeys(1, 19), createTestValues("db1", 1, 19))
   147  
   148  		require.True(t, itr.First())
   149  		require.False(t, itr.Prev())
   150  		checkItrResults(t, itr, createTestKeys(0, 19), createTestValues("db1", 0, 19))
   151  
   152  		require.True(t, itr.First())
   153  		require.True(t, itr.Last())
   154  		checkItrResults(t, itr, nil, nil)
   155  	})
   156  
   157  	t.Run("test-error-path", func(t *testing.T) {
   158  		env.provider.Close()
   159  		itr, err := db1.GetIterator(nil, nil)
   160  		require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed")
   161  		require.Nil(t, itr)
   162  	})
   163  }
   164  
   165  func TestBatchedUpdates(t *testing.T) {
   166  	env := newTestProviderEnv(t, testDBPath)
   167  	defer env.cleanup()
   168  	p := env.provider
   169  
   170  	db1 := p.GetDBHandle("db1")
   171  	db2 := p.GetDBHandle("db2")
   172  
   173  	dbs := []*DBHandle{db1, db2}
   174  	for _, db := range dbs {
   175  		batch := db.NewUpdateBatch()
   176  		batch.Put([]byte("key1"), []byte("value1"))
   177  		batch.Put([]byte("key2"), []byte("value2"))
   178  		batch.Put([]byte("key3"), []byte("value3"))
   179  		db.WriteBatch(batch, true)
   180  	}
   181  
   182  	for _, db := range dbs {
   183  		batch := db.NewUpdateBatch()
   184  		batch.Delete([]byte("key2"))
   185  		db.WriteBatch(batch, true)
   186  	}
   187  
   188  	for _, db := range dbs {
   189  		val1, _ := db.Get([]byte("key1"))
   190  		require.Equal(t, "value1", string(val1))
   191  
   192  		val2, err2 := db.Get([]byte("key2"))
   193  		require.NoError(t, err2, "")
   194  		require.Nil(t, val2)
   195  
   196  		val3, _ := db.Get([]byte("key3"))
   197  		require.Equal(t, "value3", string(val3))
   198  	}
   199  }
   200  
   201  func TestDrop(t *testing.T) {
   202  	env := newTestProviderEnv(t, testDBPath)
   203  	defer env.cleanup()
   204  	p := env.provider
   205  
   206  	db1 := p.GetDBHandle("db1")
   207  	db2 := p.GetDBHandle("db2")
   208  	db3 := p.GetDBHandle("db3")
   209  
   210  	require.Contains(t, p.dbHandles, "db1")
   211  	require.Contains(t, p.dbHandles, "db2")
   212  	require.Contains(t, p.dbHandles, "db3")
   213  
   214  	for i := 0; i < 20; i++ {
   215  		db1.Put([]byte(createTestKey(i)), []byte(createTestValue("db1", i)), false)
   216  		db2.Put([]byte(createTestKey(i)), []byte(createTestValue("db2", i)), false)
   217  	}
   218  	// db3 is used to test remove when multiple batches are needed (each long key has 125 bytes)
   219  	for i := 0; i < 10000; i++ {
   220  		db3.Put([]byte(createTestLongKey(i)), []byte(createTestValue("db3", i)), false)
   221  	}
   222  
   223  	expectedSetup := []struct {
   224  		db             *DBHandle
   225  		expectedKeys   []string
   226  		expectedValues []string
   227  	}{
   228  		{
   229  			db:             db1,
   230  			expectedKeys:   createTestKeys(0, 19),
   231  			expectedValues: createTestValues("db1", 0, 19),
   232  		},
   233  		{
   234  			db:             db2,
   235  			expectedKeys:   createTestKeys(0, 19),
   236  			expectedValues: createTestValues("db2", 0, 19),
   237  		},
   238  		{
   239  			db:             db3,
   240  			expectedKeys:   createTestLongKeys(0, 9999),
   241  			expectedValues: createTestValues("db3", 0, 9999),
   242  		},
   243  	}
   244  
   245  	for _, dbSetup := range expectedSetup {
   246  		itr, err := dbSetup.db.GetIterator(nil, nil)
   247  		require.NoError(t, err)
   248  		checkItrResults(t, itr, dbSetup.expectedKeys, dbSetup.expectedValues)
   249  		itr.Release()
   250  	}
   251  
   252  	require.NoError(t, p.Drop("db1"))
   253  	require.NoError(t, p.Drop("db3"))
   254  
   255  	require.NotContains(t, p.dbHandles, "db1")
   256  	require.NotContains(t, p.dbHandles, "db3")
   257  	require.Contains(t, p.dbHandles, "db2")
   258  
   259  	expectedResults := []struct {
   260  		db             *DBHandle
   261  		expectedKeys   []string
   262  		expectedValues []string
   263  	}{
   264  		{
   265  			db:             db1,
   266  			expectedKeys:   nil,
   267  			expectedValues: nil,
   268  		},
   269  		{
   270  			db:             db2,
   271  			expectedKeys:   createTestKeys(0, 19),
   272  			expectedValues: createTestValues("db2", 0, 19),
   273  		},
   274  		{
   275  			db:             db3,
   276  			expectedKeys:   nil,
   277  			expectedValues: nil,
   278  		},
   279  	}
   280  
   281  	for _, result := range expectedResults {
   282  		itr, err := result.db.GetIterator(nil, nil)
   283  		require.NoError(t, err)
   284  		checkItrResults(t, itr, result.expectedKeys, result.expectedValues)
   285  		itr.Release()
   286  	}
   287  
   288  	// negative test
   289  	p.Close()
   290  	require.EqualError(t, db2.deleteAll(), "internal leveldb error while obtaining db iterator: leveldb: closed")
   291  }
   292  
   293  func TestFormatCheck(t *testing.T) {
   294  	testCases := []struct {
   295  		dataFormat     string
   296  		dataExists     bool
   297  		expectedFormat string
   298  		expectedErr    *dataformat.ErrFormatMismatch
   299  	}{
   300  		{
   301  			dataFormat:     "",
   302  			dataExists:     true,
   303  			expectedFormat: "",
   304  			expectedErr:    nil,
   305  		},
   306  		{
   307  			dataFormat:     "",
   308  			dataExists:     false,
   309  			expectedFormat: "",
   310  			expectedErr:    nil,
   311  		},
   312  		{
   313  			dataFormat:     "",
   314  			dataExists:     false,
   315  			expectedFormat: "2.0",
   316  			expectedErr:    nil,
   317  		},
   318  		{
   319  			dataFormat:     "",
   320  			dataExists:     true,
   321  			expectedFormat: "2.0",
   322  			expectedErr:    &dataformat.ErrFormatMismatch{Format: "", ExpectedFormat: "2.0"},
   323  		},
   324  		{
   325  			dataFormat:     "2.0",
   326  			dataExists:     true,
   327  			expectedFormat: "2.0",
   328  			expectedErr:    nil,
   329  		},
   330  		{
   331  			dataFormat:     "2.0",
   332  			dataExists:     true,
   333  			expectedFormat: "3.0",
   334  			expectedErr:    &dataformat.ErrFormatMismatch{Format: "2.0", ExpectedFormat: "3.0"},
   335  		},
   336  	}
   337  
   338  	for i, testCase := range testCases {
   339  		t.Run(
   340  			fmt.Sprintf("testCase %d", i),
   341  			func(t *testing.T) {
   342  				testFormatCheck(t, testCase.dataFormat, testCase.expectedFormat, testCase.dataExists, testCase.expectedErr)
   343  			})
   344  	}
   345  }
   346  
   347  func TestClose(t *testing.T) {
   348  	env := newTestProviderEnv(t, testDBPath)
   349  	defer env.cleanup()
   350  	p := env.provider
   351  
   352  	db1 := p.GetDBHandle("db1")
   353  	db2 := p.GetDBHandle("db2")
   354  
   355  	expectedDBHandles := map[string]*DBHandle{
   356  		"db1": db1,
   357  		"db2": db2,
   358  	}
   359  	require.Equal(t, expectedDBHandles, p.dbHandles)
   360  
   361  	db1.Close()
   362  	expectedDBHandles = map[string]*DBHandle{
   363  		"db2": db2,
   364  	}
   365  	require.Equal(t, expectedDBHandles, p.dbHandles)
   366  
   367  	db2.Close()
   368  	require.Equal(t, map[string]*DBHandle{}, p.dbHandles)
   369  }
   370  
   371  func TestIsEmpty(t *testing.T) {
   372  	var env *testDBProviderEnv
   373  	var db1, db2 *DBHandle
   374  
   375  	setup := func() {
   376  		env = newTestProviderEnv(t, testDBPath)
   377  		p := env.provider
   378  		db1 = p.GetDBHandle("db1")
   379  		db2 = p.GetDBHandle("db2")
   380  	}
   381  
   382  	cleanup := func() {
   383  		env.cleanup()
   384  	}
   385  
   386  	t.Run("both the dbs are empty", func(t *testing.T) {
   387  		setup()
   388  		defer cleanup()
   389  
   390  		empty, err := db1.IsEmpty()
   391  		require.NoError(t, err)
   392  		require.True(t, empty)
   393  
   394  		empty, err = db2.IsEmpty()
   395  		require.NoError(t, err)
   396  		require.True(t, empty)
   397  	})
   398  
   399  	t.Run("only one db is empty", func(t *testing.T) {
   400  		setup()
   401  		defer cleanup()
   402  
   403  		db1.Put([]byte("key"), []byte("value"), false)
   404  		empty, err := db1.IsEmpty()
   405  		require.NoError(t, err)
   406  		require.False(t, empty)
   407  
   408  		empty, err = db2.IsEmpty()
   409  		require.NoError(t, err)
   410  		require.True(t, empty)
   411  	})
   412  
   413  	t.Run("both the dbs contain data", func(t *testing.T) {
   414  		setup()
   415  		defer cleanup()
   416  
   417  		db1.Put([]byte("key"), []byte("value"), false)
   418  		db2.Put([]byte("key"), []byte("value"), false)
   419  
   420  		empty, err := db1.IsEmpty()
   421  		require.NoError(t, err)
   422  		require.False(t, empty)
   423  
   424  		empty, err = db2.IsEmpty()
   425  		require.NoError(t, err)
   426  		require.False(t, empty)
   427  	})
   428  
   429  	t.Run("iter error", func(t *testing.T) {
   430  		setup()
   431  		defer cleanup()
   432  
   433  		env.provider.Close()
   434  		empty, err := db1.IsEmpty()
   435  		require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed")
   436  		require.False(t, empty)
   437  
   438  		empty, err = db2.IsEmpty()
   439  		require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed")
   440  		require.False(t, empty)
   441  	})
   442  }
   443  
   444  func testFormatCheck(t *testing.T, dataFormat, expectedFormat string, dataExists bool, expectedErr *dataformat.ErrFormatMismatch) {
   445  	require.NoError(t, os.RemoveAll(testDBPath))
   446  	defer func() {
   447  		require.NoError(t, os.RemoveAll(testDBPath))
   448  	}()
   449  
   450  	// setup test pre-conditions (create a db with dbformat)
   451  	p, err := NewProvider(&Conf{DBPath: testDBPath, ExpectedFormat: dataFormat})
   452  	require.NoError(t, err)
   453  	f, err := p.GetDataFormat()
   454  	require.NoError(t, err)
   455  	require.Equal(t, dataFormat, f)
   456  	if dataExists {
   457  		require.NoError(t, p.GetDBHandle("testdb").Put([]byte("key"), []byte("value"), true))
   458  	}
   459  
   460  	// close and reopen with new conf
   461  	p.Close()
   462  	p, err = NewProvider(&Conf{DBPath: testDBPath, ExpectedFormat: expectedFormat})
   463  	if expectedErr != nil {
   464  		expectedErr.DBInfo = fmt.Sprintf("leveldb at [%s]", testDBPath)
   465  		require.Equal(t, err, expectedErr)
   466  		return
   467  	}
   468  	require.NoError(t, err)
   469  	f, err = p.GetDataFormat()
   470  	require.NoError(t, err)
   471  	require.Equal(t, expectedFormat, f)
   472  }
   473  
   474  func testDBBasicWriteAndReads(t *testing.T, dbNames ...string) {
   475  	env := newTestProviderEnv(t, testDBPath)
   476  	defer env.cleanup()
   477  	p := env.provider
   478  
   479  	for _, dbName := range dbNames {
   480  		db := p.GetDBHandle(dbName)
   481  		db.Put([]byte("key1"), []byte("value1_"+dbName), false)
   482  		db.Put([]byte("key2"), []byte("value2_"+dbName), false)
   483  		db.Put([]byte("key3"), []byte("value3_"+dbName), false)
   484  	}
   485  
   486  	for _, dbName := range dbNames {
   487  		db := p.GetDBHandle(dbName)
   488  		val, err := db.Get([]byte("key1"))
   489  		require.NoError(t, err, "")
   490  		require.Equal(t, []byte("value1_"+dbName), val)
   491  
   492  		val, err = db.Get([]byte("key2"))
   493  		require.NoError(t, err, "")
   494  		require.Equal(t, []byte("value2_"+dbName), val)
   495  
   496  		val, err = db.Get([]byte("key3"))
   497  		require.NoError(t, err, "")
   498  		require.Equal(t, []byte("value3_"+dbName), val)
   499  	}
   500  
   501  	for _, dbName := range dbNames {
   502  		db := p.GetDBHandle(dbName)
   503  		require.NoError(t, db.Delete([]byte("key1"), false), "")
   504  		val, err := db.Get([]byte("key1"))
   505  		require.NoError(t, err, "")
   506  		require.Nil(t, val)
   507  
   508  		require.NoError(t, db.Delete([]byte("key2"), false), "")
   509  		val, err = db.Get([]byte("key2"))
   510  		require.NoError(t, err, "")
   511  		require.Nil(t, val)
   512  
   513  		require.NoError(t, db.Delete([]byte("key3"), false), "")
   514  		val, err = db.Get([]byte("key3"))
   515  		require.NoError(t, err, "")
   516  		require.Nil(t, val)
   517  	}
   518  }
   519  
   520  func checkItrResults(t *testing.T, itr *Iterator, expectedKeys []string, expectedValues []string) {
   521  	var actualKeys []string
   522  	var actualValues []string
   523  	for itr.Next(); itr.Valid(); itr.Next() {
   524  		actualKeys = append(actualKeys, string(itr.Key()))
   525  		actualValues = append(actualValues, string(itr.Value()))
   526  	}
   527  	require.Equal(t, expectedKeys, actualKeys)
   528  	require.Equal(t, expectedValues, actualValues)
   529  	require.Equal(t, false, itr.Next())
   530  }
   531  
   532  func createTestKey(i int) string {
   533  	return fmt.Sprintf("key_%06d", i)
   534  }
   535  
   536  const padding100 = "_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_"
   537  
   538  func createTestLongKey(i int) string {
   539  	return fmt.Sprintf("key_%s_%10d", padding100, i)
   540  }
   541  
   542  func createTestValue(dbname string, i int) string {
   543  	return fmt.Sprintf("value_%s_%06d", dbname, i)
   544  }
   545  
   546  func createTestKeys(start int, end int) []string {
   547  	var keys []string
   548  	for i := start; i <= end; i++ {
   549  		keys = append(keys, createTestKey(i))
   550  	}
   551  	return keys
   552  }
   553  
   554  func createTestLongKeys(start int, end int) []string {
   555  	var keys []string
   556  	for i := start; i <= end; i++ {
   557  		keys = append(keys, createTestLongKey(i))
   558  	}
   559  	return keys
   560  }
   561  
   562  func createTestValues(dbname string, start int, end int) []string {
   563  	var values []string
   564  	for i := start; i <= end; i++ {
   565  		values = append(values, createTestValue(dbname, i))
   566  	}
   567  	return values
   568  }