mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-26 05:27:19 +00:00
573 lines
11 KiB
Go
573 lines
11 KiB
Go
package mdbx
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestEnv_Path_notOpen(t *testing.T) {
|
|
env, err := NewEnv()
|
|
if err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
defer env.Close()
|
|
|
|
// before Open the Path method returns "" and a non-nil error.
|
|
path, err := env.Path()
|
|
if err == nil {
|
|
t.Errorf("no error returned before Open")
|
|
}
|
|
if path != "" {
|
|
t.Errorf("non-zero path returned before Open")
|
|
}
|
|
}
|
|
|
|
func TestEnv_Path(t *testing.T) {
|
|
env, err := NewEnv()
|
|
if err != nil {
|
|
t.Fatalf("create: %v", err)
|
|
}
|
|
|
|
// open an environment
|
|
dir := t.TempDir()
|
|
err = env.Open(dir, 0, 0644)
|
|
defer env.Close()
|
|
if err != nil {
|
|
t.Errorf("open: %v", err)
|
|
}
|
|
path, err := env.Path()
|
|
if err != nil {
|
|
t.Errorf("path: %v", err)
|
|
}
|
|
if path != dir {
|
|
t.Errorf("path: %q (!= %q)", path, dir)
|
|
}
|
|
}
|
|
|
|
func TestEnv_Open_notExist(t *testing.T) {
|
|
env, err := NewEnv()
|
|
if err != nil {
|
|
t.Fatalf("create: %s", err)
|
|
}
|
|
defer env.Close()
|
|
|
|
// ensure that opening a non-existent path fails.
|
|
err = env.Open("/path/does/not/exist/aoeu", 0, 0664)
|
|
if !IsNotExist(err) {
|
|
t.Errorf("open: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestEnv_Open(t *testing.T) {
|
|
env, err1 := NewEnv()
|
|
if err1 != nil {
|
|
t.Error(err1)
|
|
return
|
|
}
|
|
defer env.Close()
|
|
|
|
// open an environment at a temporary path.
|
|
path := t.TempDir()
|
|
err := env.Open(path, 0, 0664)
|
|
if err != nil {
|
|
t.Errorf("open: %s", err)
|
|
}
|
|
}
|
|
|
|
func TestEnv_FD(t *testing.T) {
|
|
if runtime.GOOS == "windows" {
|
|
t.Skip("FD funcs not supported on windows")
|
|
}
|
|
env, err1 := NewEnv()
|
|
if err1 != nil {
|
|
t.Error(err1)
|
|
return
|
|
}
|
|
defer env.Close()
|
|
|
|
fd, err := env.FD()
|
|
if err != nil && !strings.Contains(err.Error(), "operation not permitted") {
|
|
t.Errorf("fd: %x (%v)", fd, err)
|
|
}
|
|
|
|
// open an environment at a temporary path.
|
|
path := t.TempDir()
|
|
err = env.Open(path, 0, 0664)
|
|
if err != nil {
|
|
t.Errorf("open: %s", err)
|
|
}
|
|
|
|
fd, err = env.FD()
|
|
if err != nil {
|
|
t.Errorf("fd error: %v", err)
|
|
}
|
|
if fd == 0 {
|
|
t.Errorf("fd: %x", fd)
|
|
}
|
|
}
|
|
|
|
func TestEnv_Flags(t *testing.T) {
|
|
env := setup(t)
|
|
|
|
flags, err := env.Flags()
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
if flags&NoTLS == 0 {
|
|
t.Errorf("NoTLS is not set")
|
|
}
|
|
//if flags&SafeNoSync != 0 {
|
|
// t.Errorf("UtterlyNoSync is set")
|
|
//}
|
|
|
|
err = env.SetFlags(SafeNoSync)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
flags, err = env.Flags()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if flags&SafeNoSync == 0 {
|
|
t.Error("UtterlyNoSync is not set")
|
|
}
|
|
|
|
err = env.UnsetFlags(SafeNoSync)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
flags, err = env.Flags()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if flags&SafeNoSync != 0 {
|
|
t.Error("UtterlyNoSync is set")
|
|
}
|
|
}
|
|
|
|
func TestEnv_SetMaxReader(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
env, err := NewEnv()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
maxreaders := uint64(246)
|
|
err = env.SetOption(OptMaxReaders, maxreaders)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_maxreaders, err := env.GetOption(OptMaxReaders)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _maxreaders < maxreaders {
|
|
t.Errorf("unexpected MaxReaders: %v (< %v)", _maxreaders, maxreaders)
|
|
}
|
|
|
|
err = env.Open(dir, 0, 0644)
|
|
defer env.Close()
|
|
if err != nil {
|
|
env.Close()
|
|
t.Error(err)
|
|
}
|
|
//
|
|
//err = env.SetOption(OptMaxReaders, uint64(126))
|
|
//if !IsErrnoSys(err, syscall.EPERM) {
|
|
// t.Errorf("unexpected error: %v (!= %v)", err, syscall.EPERM)
|
|
//}
|
|
//_maxreaders, err = env.GetOption(OptMaxReaders)
|
|
//if err != nil {
|
|
// t.Error(err)
|
|
//}
|
|
//if _maxreaders < maxreaders {
|
|
// t.Errorf("unexpected MaxReaders: %v (!= %v)", _maxreaders, maxreaders)
|
|
//}
|
|
}
|
|
|
|
func TestEnv_SetDebug(t *testing.T) {
|
|
env, err := NewEnv()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
err = env.SetDebug(LogLvlDoNotChange, DbgLegacyTxOverlap, LoggerDoNotChange)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
//func TestEnv_SetMapSize(t *testing.T) {
|
|
// env := setup(t)
|
|
//
|
|
//
|
|
// const minsize = 100 << 20 // 100MB
|
|
// err := env.SetMapSize(minsize)
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// }
|
|
//
|
|
// err = env.Update(func(txn *Txn) (err error) {
|
|
// return nil
|
|
// })
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// }
|
|
//
|
|
// info, err := env.Info()
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// } else if info.MapSize < minsize {
|
|
// t.Errorf("unexpected mapsize: %v (< %v)", info.MapSize, minsize)
|
|
// }
|
|
//}
|
|
|
|
//func TestEnv_ReaderList(t *testing.T) {
|
|
// env := setup(t)
|
|
//
|
|
//
|
|
// var numreaders = 2
|
|
//
|
|
// var fin sync.WaitGroup
|
|
// defer fin.Wait()
|
|
// ready := make(chan struct{})
|
|
// done := make(chan struct{})
|
|
// defer close(done)
|
|
//
|
|
// t.Logf("starting")
|
|
//
|
|
// for i := 0; i < numreaders; i++ {
|
|
// fin.Add(1)
|
|
// go func(i int) {
|
|
// defer fin.Done()
|
|
// err := env.View(func(txn *Txn) (err error) {
|
|
// t.Logf("reader %v: ready", i)
|
|
// ready <- struct{}{}
|
|
//
|
|
// <-done
|
|
// t.Logf("reader %v: done", i)
|
|
// return nil
|
|
// })
|
|
// if err != nil {
|
|
// t.Errorf("reader %d: %q", i, err)
|
|
// }
|
|
// }(i)
|
|
//
|
|
// // wait for each reader to become ready
|
|
// <-ready
|
|
// }
|
|
//
|
|
// var readers []string
|
|
// _ = env.ReaderList(func(msg string) error {
|
|
// t.Logf("reader: %q", msg)
|
|
// readers = append(readers, msg)
|
|
// return nil
|
|
// })
|
|
// if len(readers) != numreaders+1 {
|
|
// t.Errorf("unexpected reader list size: %d (!= %d)", len(readers), numreaders)
|
|
// }
|
|
//}
|
|
|
|
//func TestEnv_ReaderList_error(t *testing.T) {
|
|
// env := setup(t)
|
|
//
|
|
//
|
|
// var numreaders = 2
|
|
//
|
|
// var fin sync.WaitGroup
|
|
// defer fin.Wait()
|
|
// ready := make(chan struct{})
|
|
// done := make(chan struct{})
|
|
// defer close(done)
|
|
//
|
|
// t.Logf("starting")
|
|
//
|
|
// for i := 0; i < numreaders; i++ {
|
|
// fin.Add(1)
|
|
// go func(i int) {
|
|
// defer fin.Done()
|
|
// err := env.View(func(txn *Txn) (err error) {
|
|
// t.Logf("reader %v: ready", i)
|
|
// ready <- struct{}{}
|
|
//
|
|
// <-done
|
|
// t.Logf("reader %v: done", i)
|
|
// return nil
|
|
// })
|
|
// if err != nil {
|
|
// t.Errorf("reader %d: %q", i, err)
|
|
// }
|
|
// }(i)
|
|
//
|
|
// // wait for each reader to become ready
|
|
// <-ready
|
|
// }
|
|
//
|
|
// e := fmt.Errorf("testerror")
|
|
// var readers []string
|
|
// err := env.ReaderList(func(msg string) error {
|
|
// readers = append(readers, msg)
|
|
// return e
|
|
// })
|
|
// if err == nil {
|
|
// t.Errorf("expected error")
|
|
// }
|
|
// if !errors.Is(err, e) {
|
|
// t.Errorf("unexpected error: %q (!= %q)", err, e)
|
|
// }
|
|
// if len(readers) != 1 {
|
|
// t.Errorf("unexpected reader list size: %d (!= %d)", len(readers), 1)
|
|
// }
|
|
//}
|
|
//
|
|
//func TestEnv_ReaderList_envInvalid(t *testing.T) {
|
|
// err := (&Env{}).ReaderList(func(msg string) error {
|
|
// t.Logf("%s", msg)
|
|
// return nil
|
|
// })
|
|
// if err == nil {
|
|
// t.Errorf("expected error")
|
|
// }
|
|
//}
|
|
//
|
|
//func TestEnv_ReaderList_nilFunc(t *testing.T) {
|
|
// env, err := NewEnv()
|
|
// if err != nil {
|
|
// t.Fatal(err)
|
|
// }
|
|
// err = env.ReaderList(nil)
|
|
// if err == nil {
|
|
// t.Errorf("expected error")
|
|
// }
|
|
//}
|
|
|
|
func TestEnv_ReaderCheck(t *testing.T) {
|
|
env := setup(t)
|
|
|
|
numDead, err := env.ReaderCheck()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if numDead != 0 {
|
|
t.Errorf("unexpected dead readers: %v (!= %v)", numDead, 0)
|
|
}
|
|
}
|
|
|
|
//func TestEnv_Copy(t *testing.T) {
|
|
// testEnvCopy(t, 0, false, false)
|
|
//}
|
|
//
|
|
//func TestEnv_CopyFlags(t *testing.T) {
|
|
// testEnvCopy(t, CopyCompact, true, false)
|
|
//}
|
|
//
|
|
//func TestEnv_CopyFlags_zero(t *testing.T) {
|
|
// testEnvCopy(t, 0, true, false)
|
|
//}
|
|
//
|
|
//func TestEnv_CopyFD(t *testing.T) {
|
|
// testEnvCopy(t, 0, false, true)
|
|
//}
|
|
//
|
|
//func TestEnv_CopyFDFlags(t *testing.T) {
|
|
// testEnvCopy(t, CopyCompact, true, true)
|
|
//}
|
|
//
|
|
//func TestEnv_CopyFDFlags_zero(t *testing.T) {
|
|
// testEnvCopy(t, 0, true, true)
|
|
//}
|
|
//
|
|
//func testEnvCopy(t *testing.T, flags uint, useflags bool, usefd bool) {
|
|
// dircp, err := ioutil.TempDir("", "test-env-copy-")
|
|
// if err != nil {
|
|
// t.Fatal(err)
|
|
// }
|
|
// defer os.RemoveAll(dircp)
|
|
//
|
|
// var fd uintptr
|
|
// if usefd {
|
|
// path := filepath.Join(dircp, "data.mdb")
|
|
// f, err := os.Create(path)
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// return
|
|
// }
|
|
// fd = f.Fd()
|
|
// defer f.Close()
|
|
// }
|
|
//
|
|
// env := setup(t)
|
|
//
|
|
//
|
|
// item := struct{ k, v []byte }{
|
|
// []byte("k0"),
|
|
// []byte("v0"),
|
|
// }
|
|
//
|
|
// err = env.Update(func(txn *Txn) (err error) {
|
|
// db, err := txn.OpenRoot(0)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// return txn.Put(db, item.k, item.v, 0)
|
|
// })
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// }
|
|
//
|
|
// switch {
|
|
// case usefd && useflags:
|
|
// err = env.CopyFDFlag(fd, flags)
|
|
// case usefd && !useflags:
|
|
// err = env.CopyFD(fd)
|
|
// case !usefd && useflags:
|
|
// err = env.CopyFlag(dircp, flags)
|
|
// case !usefd && !useflags:
|
|
// err = env.Copy(dircp)
|
|
// }
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// }
|
|
//
|
|
// envcp, err := NewEnv()
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// }
|
|
// err = envcp.Open(dircp, 0, 0644)
|
|
// defer envcp.Close()
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// return
|
|
// }
|
|
//
|
|
// err = envcp.View(func(txn *Txn) (err error) {
|
|
// db, err := txn.OpenRoot(0)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// v, err := txn.Get(db, item.k)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
// if !bytes.Equal(v, item.v) {
|
|
// return fmt.Errorf("unexpected value: %q (!= %q)", v, "v0")
|
|
// }
|
|
// return nil
|
|
// })
|
|
// if err != nil {
|
|
// t.Error(err)
|
|
// }
|
|
//}
|
|
|
|
func TestEnv_Sync(t *testing.T) {
|
|
env := setupFlags(t, SafeNoSync)
|
|
|
|
item := struct{ k, v []byte }{[]byte("k0"), []byte("v0")}
|
|
|
|
err := env.Update(func(txn *Txn) (err error) {
|
|
db, err := txn.OpenRoot(0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return txn.Put(db, item.k, item.v, 0)
|
|
})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
err = env.Sync(true, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func setup(t testing.TB) *Env {
|
|
return setupFlags(t, 0)
|
|
}
|
|
|
|
func setupFlags(t testing.TB, flags uint) *Env {
|
|
env, err := NewEnv()
|
|
if err != nil {
|
|
t.Fatalf("env: %s", err)
|
|
}
|
|
path := t.TempDir()
|
|
err = env.SetOption(OptMaxDB, 1024)
|
|
if err != nil {
|
|
t.Fatalf("setmaxdbs: %v", err)
|
|
}
|
|
const pageSize = 4096
|
|
err = env.SetGeometry(-1, -1, 64*1024*pageSize, -1, -1, pageSize)
|
|
if err != nil {
|
|
t.Fatalf("setmaxdbs: %v", err)
|
|
}
|
|
err = env.Open(path, flags, 0664)
|
|
if err != nil {
|
|
t.Fatalf("open: %s", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
env.Close()
|
|
})
|
|
return env
|
|
}
|
|
|
|
type T interface {
|
|
Errorf(format string, vals ...interface{})
|
|
Fatalf(format string, vals ...interface{})
|
|
}
|
|
|
|
func TestEnv_MaxKeySize(t *testing.T) {
|
|
env := setup(t)
|
|
|
|
n := env.MaxKeySize()
|
|
if n <= 0 {
|
|
t.Errorf("invaild maxkeysize: %d", n)
|
|
}
|
|
}
|
|
|
|
func TestEnv_MaxKeySize_nil(t *testing.T) {
|
|
var env *Env
|
|
n := env.MaxKeySize()
|
|
if n < -1 {
|
|
t.Errorf("invaild maxkeysize: %d", n)
|
|
}
|
|
t.Logf("mdb_env_get_maxkeysize: %d", n)
|
|
}
|
|
|
|
func TestEnv_CloseDBI(t *testing.T) {
|
|
env := setup(t)
|
|
|
|
const numdb = 1000
|
|
for i := 0; i < numdb; i++ {
|
|
dbname := fmt.Sprintf("db%d", i)
|
|
|
|
var dbi DBI
|
|
err := env.Update(func(txn *Txn) (err error) {
|
|
dbi, err = txn.CreateDBI(dbname)
|
|
return err
|
|
})
|
|
if err != nil {
|
|
t.Errorf("%s", err)
|
|
}
|
|
|
|
env.CloseDBI(dbi)
|
|
}
|
|
|
|
stat, err := env.Stat()
|
|
if err != nil {
|
|
t.Errorf("%s", err)
|
|
return
|
|
}
|
|
|
|
//nolint:goerr113
|
|
if stat.Entries != numdb {
|
|
t.Errorf("unexpected entries: %d (not %d)", stat.Entries, numdb)
|
|
}
|
|
}
|