mirror of https://github.com/etcd-io/bbolt.git
Mock OS and File.
parent
746c287b26
commit
28c1e86a27
16
db.go
16
db.go
|
@ -1,7 +1,7 @@
|
||||||
package bolt
|
package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -26,9 +26,9 @@ type DB struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
opened bool
|
opened bool
|
||||||
|
|
||||||
os OS
|
os _os
|
||||||
file *File
|
file file
|
||||||
metafile *File
|
metafile file
|
||||||
data []byte
|
data []byte
|
||||||
buf []byte
|
buf []byte
|
||||||
meta0 *meta
|
meta0 *meta
|
||||||
|
@ -56,14 +56,14 @@ type DB struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDB() *DB {
|
func NewDB() *DB {
|
||||||
return &DB{os: &sysos{}}
|
return &DB{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Path() string {
|
func (db *DB) Path() string {
|
||||||
return db.path
|
return db.path
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Open(path string, mode FileMode) error {
|
func (db *DB) Open(path string, mode os.FileMode) error {
|
||||||
var err error
|
var err error
|
||||||
db.Lock()
|
db.Lock()
|
||||||
defer db.Unlock()
|
defer db.Unlock()
|
||||||
|
@ -79,11 +79,11 @@ func (db *DB) Open(path string, mode FileMode) error {
|
||||||
|
|
||||||
// Open data file and separate sync handler for metadata writes.
|
// Open data file and separate sync handler for metadata writes.
|
||||||
db.path = path
|
db.path = path
|
||||||
if db.file, err = db.os.OpenFile(db.path, O_RDWR|O_CREATE, mode); err != nil {
|
if db.file, err = db.os.OpenFile(db.path, os.O_RDWR|os.O_CREATE, mode); err != nil {
|
||||||
db.close()
|
db.close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if db.metafile, err = db.os.OpenFile(db.path, O_RDWR|O_SYNC, mode); err != nil {
|
if db.metafile, err = db.os.OpenFile(db.path, os.O_RDWR|os.O_SYNC, mode); err != nil {
|
||||||
db.close()
|
db.close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
41
db_test.go
41
db_test.go
|
@ -8,13 +8,46 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ensure that a database can be opened without error.
|
||||||
func TestDBOpen(t *testing.T) {
|
func TestDBOpen(t *testing.T) {
|
||||||
withDB(func(db *DB, path string) {
|
withDB(func(db *DB, path string) {
|
||||||
err := db.Open(path, 0666)
|
err := db.Open(path, 0666)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, db.Path(), path)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that the database returns an error if already open.
|
||||||
|
func TestDBReopen(t *testing.T) {
|
||||||
|
withDB(func(db *DB, path string) {
|
||||||
|
db.Open(path, 0666)
|
||||||
|
err := db.Open(path, 0666)
|
||||||
|
assert.Equal(t, err, DatabaseAlreadyOpenedError)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the database returns an error if the file handle cannot be open.
|
||||||
|
func TestDBOpenFileError(t *testing.T) {
|
||||||
|
withMockDB(func(db *DB, mockos *mockos, path string) {
|
||||||
|
exp := &os.PathError{}
|
||||||
|
mockos.On("OpenFile", path, os.O_RDWR|os.O_CREATE, os.FileMode(0666)).Return((*os.File)(nil), exp)
|
||||||
|
err := db.Open(path, 0666)
|
||||||
|
assert.Equal(t, err, exp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the database returns an error if the meta file handle cannot be open.
|
||||||
|
func TestDBOpenMetaFileError(t *testing.T) {
|
||||||
|
withMockDB(func(db *DB, mockos *mockos, path string) {
|
||||||
|
exp := &os.PathError{}
|
||||||
|
mockos.On("OpenFile", path, os.O_RDWR|os.O_CREATE, os.FileMode(0666)).Return(&os.File{}, nil)
|
||||||
|
mockos.On("OpenFile", path, os.O_RDWR|os.O_SYNC, os.FileMode(0666)).Return((*os.File)(nil), exp)
|
||||||
|
err := db.Open(path, 0666)
|
||||||
|
assert.Equal(t, err, exp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// withDB executes a function with a database reference.
|
||||||
func withDB(fn func(*DB, string)) {
|
func withDB(fn func(*DB, string)) {
|
||||||
f, _ := ioutil.TempFile("", "bolt-")
|
f, _ := ioutil.TempFile("", "bolt-")
|
||||||
path := f.Name()
|
path := f.Name()
|
||||||
|
@ -25,3 +58,11 @@ func withDB(fn func(*DB, string)) {
|
||||||
db := NewDB()
|
db := NewDB()
|
||||||
fn(db, path)
|
fn(db, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// withMockDB executes a function with a database reference and a mock filesystem.
|
||||||
|
func withMockDB(fn func(*DB, *mockos, string)) {
|
||||||
|
os := &mockos{}
|
||||||
|
db := NewDB()
|
||||||
|
db.os = os
|
||||||
|
fn(db, os, "/mock/db")
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package bolt
|
||||||
|
|
||||||
|
type file interface {
|
||||||
|
Fd() uintptr
|
||||||
|
Name() string
|
||||||
|
ReadAt(b []byte, off int64) (n int, err error)
|
||||||
|
WriteAt(b []byte, off int64) (n int, err error)
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package bolt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockfile struct {
|
||||||
|
mock.Mock
|
||||||
|
fd uintptr
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockfile) Fd() uintptr {
|
||||||
|
return m.fd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockfile) Name() string {
|
||||||
|
return m.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockfile) ReadAt(b []byte, off int64) (n int, err error) {
|
||||||
|
args := m.Called(b, off)
|
||||||
|
return args.Int(0), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockfile) WriteAt(b []byte, off int64) (n int, err error) {
|
||||||
|
args := m.Called(b, off)
|
||||||
|
return args.Int(0), args.Error(1)
|
||||||
|
}
|
2
os.go
2
os.go
|
@ -4,7 +4,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OS interface {
|
type _os interface {
|
||||||
OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error)
|
OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error)
|
||||||
Stat(name string) (fi os.FileInfo, err error)
|
Stat(name string) (fi os.FileInfo, err error)
|
||||||
Getpagesize() int
|
Getpagesize() int
|
||||||
|
|
Loading…
Reference in New Issue