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 }