为什么 leveldb 错误只出现在 10% 的测试运行中,如何解决?

Why is leveldb error appears only in 10% of test runs and how to solve it?

我正在使用 leveldb 的 go 版本来存储我的数据。我做了一些简单的辅助函数来操作数据库。我还为他们写了一个测试(如下)。但是测试在大约 10% 的运行中抛出错误(下面的堆栈跟踪)。那个错误的原因是什么,我该如何解决?

帮手:

package data

import (
    "path"
    "runtime"

    "github.com/syndtr/goleveldb/leveldb"
)

var base = openDB()

func openDB() *leveldb.DB {
    _, filename, _, _ := runtime.Caller(0)
    dbPath := path.Dir(filename) + "/leveldb"
    db, _ := leveldb.OpenFile(dbPath, nil)
    return db
}

// get value by key from database
func Get(key []byte) []byte {
    output, getErr := base.Get(key, nil)
    if getErr != nil {
        return nil
    }
    return output
}

// put key by some value to database (if value exists use Change()
// func instead)
func Put(key []byte, value []byte) {
    valueExists, _ := base.Has(key, nil)
    if valueExists {
        return
    }
    base.Put(key, value, nil)
}

// function is made only to remove values after testing, dont call it in
// any other case
func TestRM(key []byte) {
    base.Delete(key, nil)
}

测试:


func TestPutValue(t *testing.T) {
    key := []byte{1, 2, 3}
    val := []byte{1, 2, 3, 4, 5}
    Put(key, val)
    val2 := Get(key)
    if !reflect.DeepEqual(val, val2) {
        t.Error("values are not equal")
    }
    TestRM(key)
}

堆栈跟踪:

--- FAIL: TestPutValue (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x188 pc=0x1149a7c]

goroutine 6 [running]:
testing.tRunner.func1.2(0x1188020, 0x12d05c0)
    /usr/local/go/src/testing/testing.go:1143 +0x332
testing.tRunner.func1(0xc000001380)
    /usr/local/go/src/testing/testing.go:1146 +0x4b6
panic(0x1188020, 0x12d05c0)
    /usr/local/go/src/runtime/panic.go:965 +0x1b9
github.com/syndtr/goleveldb/leveldb.(*DB).isClosed(...)
    /Users/danilafominyh/go/pkg/mod/github.com/syndtr/goleveldb@v1.0.0/leveldb/db_state.go:230
github.com/syndtr/goleveldb/leveldb.(*DB).ok(...)
    /Users/danilafominyh/go/pkg/mod/github.com/syndtr/goleveldb@v1.0.0/leveldb/db_state.go:235
github.com/syndtr/goleveldb/leveldb.(*DB).Has(0x0, 0xc00001c1a8, 0x3, 0x3, 0x0, 0xc000038600, 0x0, 0x0)
    /Users/danilafominyh/go/pkg/mod/github.com/syndtr/goleveldb@v1.0.0/leveldb/db.go:852 +0x5c
sync_tree/data.Put(0xc00001c1a8, 0x3, 0x3, 0xc00001c1ab, 0x5, 0x5)
    /Users/danilafominyh/Documents/sync_tree_server/data/database.go:31 +0x58
sync_tree/data.TestPutValue(0xc000001380)
    /Users/danilafominyh/Documents/sync_tree_server/data/database_test.go:11 +0xb3
testing.tRunner(0xc000001380, 0x11c4b68)
    /usr/local/go/src/testing/testing.go:1193 +0xef
created by testing.(*T).Run
    /usr/local/go/src/testing/testing.go:1238 +0x2b3
FAIL    sync_tree/data  0.167s
FAIL
Error: Tests failed.

应用程序很可能在 db, _ := leveldb.OpenFile(dbPath, nil) 行中出现错误,该错误被忽略。使 openDBleveldb.OpenFile return 出错或 return 出错时恐慌

func openDB() *leveldb.DB {
    _, filename, _, _ := runtime.Caller(0)
    dbPath := path.Dir(filename) + "/leveldb"
    db, err := leveldb.OpenFile(dbPath, nil)
    if err != nil {
        panic(fmt.Errorf("could not open leveldb database: %w", err))
    }
    return db
}

免责声明:它不会解决问题,但会告诉您哪里出了问题。