github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/util/leveldbhelper/leveldb_helper_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  	"path/filepath"
    13  	"testing"
    14  
    15  	"github.com/stretchr/testify/require"
    16  	"github.com/syndtr/goleveldb/leveldb"
    17  )
    18  
    19  func TestLevelDBHelperWriteWithoutOpen(t *testing.T) {
    20  	env := newTestDBEnv(t, testDBPath)
    21  	defer env.cleanup()
    22  	db := env.db
    23  	defer func() {
    24  		if recover() == nil {
    25  			t.Fatalf("A panic is expected when writing to db before opening")
    26  		}
    27  	}()
    28  	db.Put([]byte("key"), []byte("value"), false)
    29  }
    30  
    31  func TestLevelDBHelperReadWithoutOpen(t *testing.T) {
    32  	env := newTestDBEnv(t, testDBPath)
    33  	defer env.cleanup()
    34  	db := env.db
    35  	defer func() {
    36  		if recover() == nil {
    37  			t.Fatalf("A panic is expected when writing to db before opening")
    38  		}
    39  	}()
    40  	db.Get([]byte("key"))
    41  }
    42  
    43  func TestLevelDBHelper(t *testing.T) {
    44  	env := newTestDBEnv(t, testDBPath)
    45  	// defer env.cleanup()
    46  	db := env.db
    47  
    48  	db.Open()
    49  	// second time open should not have any side effect
    50  	db.Open()
    51  	IsEmpty, err := db.IsEmpty()
    52  	require.NoError(t, err)
    53  	require.True(t, IsEmpty)
    54  	db.Put([]byte("key1"), []byte("value1"), false)
    55  	db.Put([]byte("key2"), []byte("value2"), true)
    56  	db.Put([]byte("key3"), []byte("value3"), true)
    57  
    58  	val, _ := db.Get([]byte("key2"))
    59  	require.Equal(t, "value2", string(val))
    60  
    61  	db.Delete([]byte("key1"), false)
    62  	db.Delete([]byte("key2"), true)
    63  
    64  	val1, err1 := db.Get([]byte("key1"))
    65  	require.NoError(t, err1, "")
    66  	require.Equal(t, "", string(val1))
    67  
    68  	val2, err2 := db.Get([]byte("key2"))
    69  	require.NoError(t, err2, "")
    70  	require.Equal(t, "", string(val2))
    71  
    72  	db.Close()
    73  	// second time Close should not have any side effect
    74  	db.Close()
    75  
    76  	_, err = db.IsEmpty()
    77  	require.Error(t, err)
    78  
    79  	val3, err3 := db.Get([]byte("key3"))
    80  	require.Error(t, err3)
    81  	require.Equal(t, "", string(val3))
    82  
    83  	db.Open()
    84  	IsEmpty, err = db.IsEmpty()
    85  	require.NoError(t, err)
    86  	require.False(t, IsEmpty)
    87  
    88  	batch := &leveldb.Batch{}
    89  	batch.Put([]byte("key1"), []byte("value1"))
    90  	batch.Put([]byte("key2"), []byte("value2"))
    91  	batch.Delete([]byte("key3"))
    92  	db.WriteBatch(batch, true)
    93  
    94  	val1, err1 = db.Get([]byte("key1"))
    95  	require.NoError(t, err1, "")
    96  	require.Equal(t, "value1", string(val1))
    97  
    98  	val2, err2 = db.Get([]byte("key2"))
    99  	require.NoError(t, err2, "")
   100  	require.Equal(t, "value2", string(val2))
   101  
   102  	val3, err3 = db.Get([]byte("key3"))
   103  	require.NoError(t, err3, "")
   104  	require.Equal(t, "", string(val3))
   105  
   106  	keys := []string{}
   107  	itr := db.GetIterator(nil, nil)
   108  	for itr.Next() {
   109  		keys = append(keys, string(itr.Key()))
   110  	}
   111  	require.Equal(t, []string{"key1", "key2"}, keys)
   112  }
   113  
   114  func TestFileLock(t *testing.T) {
   115  	// create 1st fileLock manager
   116  	fileLockPath := testDBPath + "/fileLock"
   117  	fileLock1 := NewFileLock(fileLockPath)
   118  	require.Nil(t, fileLock1.db)
   119  	require.Equal(t, fileLock1.filePath, fileLockPath)
   120  
   121  	// acquire the file lock using the fileLock manager 1
   122  	err := fileLock1.Lock()
   123  	require.NoError(t, err)
   124  	require.NotNil(t, fileLock1.db)
   125  
   126  	// create 2nd fileLock manager
   127  	fileLock2 := NewFileLock(fileLockPath)
   128  	require.Nil(t, fileLock2.db)
   129  	require.Equal(t, fileLock2.filePath, fileLockPath)
   130  
   131  	// try to acquire the file lock again using the fileLock2
   132  	// would result in an error
   133  	err = fileLock2.Lock()
   134  	expectedErr := fmt.Sprintf("lock is already acquired on file %s", fileLockPath)
   135  	require.EqualError(t, err, expectedErr)
   136  	require.Nil(t, fileLock2.db)
   137  
   138  	// release the file lock acquired using fileLock1
   139  	fileLock1.Unlock()
   140  	require.Nil(t, fileLock1.db)
   141  
   142  	// As the fileLock1 has released the lock,
   143  	// the fileLock2 can acquire the lock.
   144  	err = fileLock2.Lock()
   145  	require.NoError(t, err)
   146  	require.NotNil(t, fileLock2.db)
   147  
   148  	// release the file lock acquired using fileLock 2
   149  	fileLock2.Unlock()
   150  	require.Nil(t, fileLock1.db)
   151  
   152  	// unlock can be called multiple times and it is safe
   153  	fileLock2.Unlock()
   154  	require.Nil(t, fileLock1.db)
   155  
   156  	// cleanup
   157  	require.NoError(t, os.RemoveAll(fileLockPath))
   158  }
   159  
   160  func TestFileLockLockUnlockLock(t *testing.T) {
   161  	// create an open lock
   162  	lockPath := testDBPath + "/fileLock"
   163  	lock := NewFileLock(lockPath)
   164  	require.Nil(t, lock.db)
   165  	require.Equal(t, lock.filePath, lockPath)
   166  	require.False(t, lock.IsLocked())
   167  
   168  	defer lock.Unlock()
   169  	defer os.RemoveAll(lockPath)
   170  
   171  	// lock
   172  	require.NoError(t, lock.Lock())
   173  	require.True(t, lock.IsLocked())
   174  
   175  	// lock
   176  	require.ErrorContains(t, lock.Lock(), "lock is already acquired")
   177  
   178  	// unlock
   179  	lock.Unlock()
   180  	require.False(t, lock.IsLocked())
   181  
   182  	// lock - this should not error
   183  	require.NoError(t, lock.Lock())
   184  	require.True(t, lock.IsLocked())
   185  }
   186  
   187  func TestCreateDBInEmptyDir(t *testing.T) {
   188  	require.NoError(t, os.RemoveAll(testDBPath), "")
   189  	require.NoError(t, os.MkdirAll(testDBPath, 0o775), "")
   190  	db := CreateDB(&Conf{DBPath: testDBPath})
   191  	defer db.Close()
   192  	defer func() {
   193  		if r := recover(); r != nil {
   194  			t.Fatalf("Panic is not expected when opening db in an existing empty dir. %s", r)
   195  		}
   196  	}()
   197  	db.Open()
   198  }
   199  
   200  func TestCreateDBInNonEmptyDir(t *testing.T) {
   201  	require.NoError(t, os.RemoveAll(testDBPath), "")
   202  	require.NoError(t, os.MkdirAll(testDBPath, 0o775), "")
   203  	file, err := os.Create(filepath.Join(testDBPath, "dummyfile.txt"))
   204  	require.NoError(t, err, "")
   205  	file.Close()
   206  	db := CreateDB(&Conf{DBPath: testDBPath})
   207  	defer db.Close()
   208  	defer func() {
   209  		if r := recover(); r == nil {
   210  			t.Fatalf("A panic is expected when opening db in an existing non-empty dir. %s", r)
   211  		}
   212  	}()
   213  	db.Open()
   214  }