Browse Source

db: test panic on nil key

pull/1842/head
Ethan Buchman 7 years ago
parent
commit
5b7f90dfb2
5 changed files with 77 additions and 17 deletions
  1. +48
    -11
      db/backend_test.go
  2. +8
    -0
      db/fsdb.go
  3. +6
    -0
      db/go_level_db.go
  4. +8
    -6
      db/mem_db.go
  5. +7
    -0
      db/types.go

+ 48
- 11
db/backend_test.go View File

@ -2,42 +2,79 @@ package db
import ( import (
"fmt" "fmt"
"os"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
) )
func testBackend(t *testing.T, backend string) {
func testBackendGetSetDelete(t *testing.T, backend string) {
// Default // Default
dir, dirname := cmn.Tempdir(fmt.Sprintf("test_backend_%s_", backend)) dir, dirname := cmn.Tempdir(fmt.Sprintf("test_backend_%s_", backend))
defer dir.Close() defer dir.Close()
db := NewDB("testdb", backend, dirname) db := NewDB("testdb", backend, dirname)
require.Nil(t, db.Get([]byte(""))) require.Nil(t, db.Get([]byte("")))
require.Nil(t, db.Get(nil))
// Set empty ("") // Set empty ("")
db.Set([]byte(""), []byte("")) db.Set([]byte(""), []byte(""))
require.NotNil(t, db.Get([]byte(""))) require.NotNil(t, db.Get([]byte("")))
require.NotNil(t, db.Get(nil))
require.Empty(t, db.Get([]byte(""))) require.Empty(t, db.Get([]byte("")))
require.Empty(t, db.Get(nil))
// Set empty (nil) // Set empty (nil)
db.Set([]byte(""), nil) db.Set([]byte(""), nil)
require.NotNil(t, db.Get([]byte(""))) require.NotNil(t, db.Get([]byte("")))
require.NotNil(t, db.Get(nil))
require.Empty(t, db.Get([]byte(""))) require.Empty(t, db.Get([]byte("")))
require.Empty(t, db.Get(nil))
// Delete // Delete
db.Delete([]byte("")) db.Delete([]byte(""))
require.Nil(t, db.Get([]byte(""))) require.Nil(t, db.Get([]byte("")))
require.Nil(t, db.Get(nil))
} }
func TestBackends(t *testing.T) {
testBackend(t, CLevelDBBackendStr)
testBackend(t, GoLevelDBBackendStr)
testBackend(t, MemDBBackendStr)
func TestBackendsGetSetDelete(t *testing.T) {
for dbType, _ := range backends {
if dbType == "fsdb" {
// TODO: handle
// fsdb cant deal with length 0 keys
continue
}
testBackendGetSetDelete(t, dbType)
}
}
func assertPanics(t *testing.T, dbType, name string, fn func()) {
defer func() {
r := recover()
assert.NotNil(t, r, cmn.Fmt("expecting %s.%s to panic", dbType, name))
}()
fn()
}
func TestBackendsNilKeys(t *testing.T) {
// test all backends
for dbType, creator := range backends {
name := cmn.Fmt("test_%x", cmn.RandStr(12))
db, err := creator(name, "")
assert.Nil(t, err)
defer os.RemoveAll(name)
assertPanics(t, dbType, "get", func() { db.Get(nil) })
assertPanics(t, dbType, "has", func() { db.Has(nil) })
assertPanics(t, dbType, "set", func() { db.Set(nil, []byte("abc")) })
assertPanics(t, dbType, "setsync", func() { db.SetSync(nil, []byte("abc")) })
assertPanics(t, dbType, "delete", func() { db.Delete(nil) })
assertPanics(t, dbType, "deletesync", func() { db.DeleteSync(nil) })
db.Close()
}
}
func TestLevelDBBackendStr(t *testing.T) {
name := cmn.Fmt("test_%x", cmn.RandStr(12))
db := NewDB(name, LevelDBBackendStr, "")
defer os.RemoveAll(name)
_, ok := db.(*GoLevelDB)
assert.True(t, ok)
} }

+ 8
- 0
db/fsdb.go View File

@ -44,6 +44,7 @@ func NewFSDB(dir string) *FSDB {
func (db *FSDB) Get(key []byte) []byte { func (db *FSDB) Get(key []byte) []byte {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
path := db.nameToPath(key) path := db.nameToPath(key)
value, err := read(path) value, err := read(path)
@ -58,6 +59,7 @@ func (db *FSDB) Get(key []byte) []byte {
func (db *FSDB) Has(key []byte) bool { func (db *FSDB) Has(key []byte) bool {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
path := db.nameToPath(key) path := db.nameToPath(key)
_, err := read(path) _, err := read(path)
@ -72,6 +74,7 @@ func (db *FSDB) Has(key []byte) bool {
func (db *FSDB) Set(key []byte, value []byte) { func (db *FSDB) Set(key []byte, value []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
db.SetNoLock(key, value) db.SetNoLock(key, value)
} }
@ -79,12 +82,14 @@ func (db *FSDB) Set(key []byte, value []byte) {
func (db *FSDB) SetSync(key []byte, value []byte) { func (db *FSDB) SetSync(key []byte, value []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
db.SetNoLock(key, value) db.SetNoLock(key, value)
} }
// NOTE: Implements atomicSetDeleter. // NOTE: Implements atomicSetDeleter.
func (db *FSDB) SetNoLock(key []byte, value []byte) { func (db *FSDB) SetNoLock(key []byte, value []byte) {
panicNilKey(key)
if value == nil { if value == nil {
value = []byte{} value = []byte{}
} }
@ -98,6 +103,7 @@ func (db *FSDB) SetNoLock(key []byte, value []byte) {
func (db *FSDB) Delete(key []byte) { func (db *FSDB) Delete(key []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
db.DeleteNoLock(key) db.DeleteNoLock(key)
} }
@ -105,12 +111,14 @@ func (db *FSDB) Delete(key []byte) {
func (db *FSDB) DeleteSync(key []byte) { func (db *FSDB) DeleteSync(key []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
db.DeleteNoLock(key) db.DeleteNoLock(key)
} }
// NOTE: Implements atomicSetDeleter. // NOTE: Implements atomicSetDeleter.
func (db *FSDB) DeleteNoLock(key []byte) { func (db *FSDB) DeleteNoLock(key []byte) {
panicNilKey(key)
err := remove(string(key)) err := remove(string(key))
if os.IsNotExist(err) { if os.IsNotExist(err) {
return return


+ 6
- 0
db/go_level_db.go View File

@ -37,6 +37,7 @@ func NewGoLevelDB(name string, dir string) (*GoLevelDB, error) {
} }
func (db *GoLevelDB) Get(key []byte) []byte { func (db *GoLevelDB) Get(key []byte) []byte {
panicNilKey(key)
res, err := db.db.Get(key, nil) res, err := db.db.Get(key, nil)
if err != nil { if err != nil {
if err == errors.ErrNotFound { if err == errors.ErrNotFound {
@ -49,6 +50,7 @@ func (db *GoLevelDB) Get(key []byte) []byte {
} }
func (db *GoLevelDB) Has(key []byte) bool { func (db *GoLevelDB) Has(key []byte) bool {
panicNilKey(key)
_, err := db.db.Get(key, nil) _, err := db.db.Get(key, nil)
if err != nil { if err != nil {
if err == errors.ErrNotFound { if err == errors.ErrNotFound {
@ -61,6 +63,7 @@ func (db *GoLevelDB) Has(key []byte) bool {
} }
func (db *GoLevelDB) Set(key []byte, value []byte) { func (db *GoLevelDB) Set(key []byte, value []byte) {
panicNilKey(key)
err := db.db.Put(key, value, nil) err := db.db.Put(key, value, nil)
if err != nil { if err != nil {
PanicCrisis(err) PanicCrisis(err)
@ -68,6 +71,7 @@ func (db *GoLevelDB) Set(key []byte, value []byte) {
} }
func (db *GoLevelDB) SetSync(key []byte, value []byte) { func (db *GoLevelDB) SetSync(key []byte, value []byte) {
panicNilKey(key)
err := db.db.Put(key, value, &opt.WriteOptions{Sync: true}) err := db.db.Put(key, value, &opt.WriteOptions{Sync: true})
if err != nil { if err != nil {
PanicCrisis(err) PanicCrisis(err)
@ -75,6 +79,7 @@ func (db *GoLevelDB) SetSync(key []byte, value []byte) {
} }
func (db *GoLevelDB) Delete(key []byte) { func (db *GoLevelDB) Delete(key []byte) {
panicNilKey(key)
err := db.db.Delete(key, nil) err := db.db.Delete(key, nil)
if err != nil { if err != nil {
PanicCrisis(err) PanicCrisis(err)
@ -82,6 +87,7 @@ func (db *GoLevelDB) Delete(key []byte) {
} }
func (db *GoLevelDB) DeleteSync(key []byte) { func (db *GoLevelDB) DeleteSync(key []byte) {
panicNilKey(key)
err := db.db.Delete(key, &opt.WriteOptions{Sync: true}) err := db.db.Delete(key, &opt.WriteOptions{Sync: true})
if err != nil { if err != nil {
PanicCrisis(err) PanicCrisis(err)


+ 8
- 6
db/mem_db.go View File

@ -27,14 +27,14 @@ func NewMemDB() *MemDB {
func (db *MemDB) Get(key []byte) []byte { func (db *MemDB) Get(key []byte) []byte {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
return db.db[string(key)] return db.db[string(key)]
} }
func (db *MemDB) Has(key []byte) bool { func (db *MemDB) Has(key []byte) bool {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
_, ok := db.db[string(key)] _, ok := db.db[string(key)]
return ok return ok
} }
@ -42,14 +42,14 @@ func (db *MemDB) Has(key []byte) bool {
func (db *MemDB) Set(key []byte, value []byte) { func (db *MemDB) Set(key []byte, value []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
db.SetNoLock(key, value) db.SetNoLock(key, value)
} }
func (db *MemDB) SetSync(key []byte, value []byte) { func (db *MemDB) SetSync(key []byte, value []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
db.SetNoLock(key, value) db.SetNoLock(key, value)
} }
@ -58,25 +58,27 @@ func (db *MemDB) SetNoLock(key []byte, value []byte) {
if value == nil { if value == nil {
value = []byte{} value = []byte{}
} }
panicNilKey(key)
db.db[string(key)] = value db.db[string(key)] = value
} }
func (db *MemDB) Delete(key []byte) { func (db *MemDB) Delete(key []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
delete(db.db, string(key)) delete(db.db, string(key))
} }
func (db *MemDB) DeleteSync(key []byte) { func (db *MemDB) DeleteSync(key []byte) {
db.mtx.Lock() db.mtx.Lock()
defer db.mtx.Unlock() defer db.mtx.Unlock()
panicNilKey(key)
delete(db.db, string(key)) delete(db.db, string(key))
} }
// NOTE: Implements atomicSetDeleter // NOTE: Implements atomicSetDeleter
func (db *MemDB) DeleteNoLock(key []byte) { func (db *MemDB) DeleteNoLock(key []byte) {
panicNilKey(key)
delete(db.db, string(key)) delete(db.db, string(key))
} }


+ 7
- 0
db/types.go View File

@ -121,3 +121,10 @@ type Iterator interface {
func bz(s string) []byte { func bz(s string) []byte {
return []byte(s) return []byte(s)
} }
// All DB funcs should panic on nil key.
func panicNilKey(key []byte) {
if key == nil {
panic("nil key")
}
}

Loading…
Cancel
Save