Skip to content
This repository has been archived by the owner on Mar 9, 2019. It is now read-only.

Commit

Permalink
Merge branch 'rhcarvalho-db-open-errors'
Browse files Browse the repository at this point in the history
  • Loading branch information
benbjohnson committed Dec 11, 2015
2 parents b34b35e + 058a7ab commit 6d4e6a3
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 28 deletions.
8 changes: 4 additions & 4 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {

// Initialize the database if it doesn't exist.
if info, err := db.file.Stat(); err != nil {
return nil, fmt.Errorf("stat error: %s", err)
return nil, err
} else if info.Size() == 0 {
// Initialize new files with meta pages.
if err := db.init(); err != nil {
Expand All @@ -189,7 +189,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
if _, err := db.file.ReadAt(buf[:], 0); err == nil {
m := db.pageInBuffer(buf[:], 0).meta()
if err := m.validate(); err != nil {
return nil, fmt.Errorf("meta0 error: %s", err)
return nil, err
}
db.pageSize = int(m.pageSize)
}
Expand Down Expand Up @@ -253,10 +253,10 @@ func (db *DB) mmap(minsz int) error {

// Validate the meta pages.
if err := db.meta0.validate(); err != nil {
return fmt.Errorf("meta0 error: %s", err)
return err
}
if err := db.meta1.validate(); err != nil {
return fmt.Errorf("meta1 error: %s", err)
return err
}

return nil
Expand Down
118 changes: 94 additions & 24 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,129 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"runtime"
"sort"
"strings"
"testing"
"time"
"unsafe"

"github.com/boltdb/bolt"
)

var statsFlag = flag.Bool("stats", false, "show performance stats")

// Ensure that opening a database with a bad path returns an error.
func TestOpen_BadPath(t *testing.T) {
db, err := bolt.Open("", 0666, nil)
assert(t, err != nil, "err: %s", err)
assert(t, db == nil, "")
// version is the data file format version.
const version = 2

// magic is the marker value to indicate that a file is a Bolt DB.
const magic uint32 = 0xED0CDAED

// pageSize is the size of one page in the data file.
const pageSize = 4096

// pageHeaderSize is the size of a page header.
const pageHeaderSize = 16

// meta represents a simplified version of a database meta page for testing.
type meta struct {
magic uint32
version uint32
_ uint32
_ uint32
_ [16]byte
_ uint64
_ uint64
_ uint64
checksum uint64
}

// Ensure that a database can be opened without error.
func TestOpen(t *testing.T) {
path := tempfile()
defer os.Remove(path)
db, err := bolt.Open(path, 0666, nil)
assert(t, db != nil, "")
ok(t, err)
equals(t, db.Path(), path)
ok(t, db.Close())
}

// Ensure that opening a database with a bad path returns an error.
func TestOpen_BadPath(t *testing.T) {
for _, path := range []string{
"",
filepath.Join(tempfile(), "youre-not-my-real-parent"),
} {
t.Logf("path = %q", path)
db, err := bolt.Open(path, 0666, nil)
assert(t, err != nil, "err: %s", err)
equals(t, path, err.(*os.PathError).Path)
equals(t, "open", err.(*os.PathError).Op)
equals(t, (*bolt.DB)(nil), db)
}
}

// Ensure that opening a file with wrong checksum returns ErrChecksum.
func TestOpen_ErrChecksum(t *testing.T) {
buf := make([]byte, pageSize)
meta := (*meta)(unsafe.Pointer(&buf[0]))
meta.magic = magic
meta.version = version
meta.checksum = 123

path := tempfile()
f, err := os.Create(path)
equals(t, nil, err)
f.WriteAt(buf, pageHeaderSize)
f.Close()
defer os.Remove(path)

_, err = bolt.Open(path, 0666, nil)
equals(t, bolt.ErrChecksum, err)
}

// Ensure that opening a file that is not a Bolt database returns ErrInvalid.
func TestOpen_ErrInvalid(t *testing.T) {
path := tempfile()

f, err := os.Create(path)
equals(t, nil, err)
fmt.Fprintln(f, "this is not a bolt database")
f.Close()
defer os.Remove(path)

_, err = bolt.Open(path, 0666, nil)
equals(t, bolt.ErrInvalid, err)
}

// Ensure that opening a file created with a different version of Bolt returns
// ErrVersionMismatch.
func TestOpen_ErrVersionMismatch(t *testing.T) {
buf := make([]byte, pageSize)
meta := (*meta)(unsafe.Pointer(&buf[0]))
meta.magic = magic
meta.version = version + 100

path := tempfile()
f, err := os.Create(path)
equals(t, nil, err)
f.WriteAt(buf, pageHeaderSize)
f.Close()
defer os.Remove(path)

_, err = bolt.Open(path, 0666, nil)
equals(t, bolt.ErrVersionMismatch, err)
}

// Ensure that opening an already open database file will timeout.
func TestOpen_Timeout(t *testing.T) {
if runtime.GOOS == "solaris" {
t.Skip("solaris fcntl locks don't support intra-process locking")
}

path := tempfile()
defer os.Remove(path)

// Open a data file.
db0, err := bolt.Open(path, 0666, nil)
Expand All @@ -68,7 +153,6 @@ func TestOpen_Wait(t *testing.T) {
}

path := tempfile()
defer os.Remove(path)

// Open a data file.
db0, err := bolt.Open(path, 0666, nil)
Expand Down Expand Up @@ -179,7 +263,6 @@ func TestOpen_Size_Large(t *testing.T) {
// Ensure that a re-opened database is consistent.
func TestOpen_Check(t *testing.T) {
path := tempfile()
defer os.Remove(path)

db, err := bolt.Open(path, 0666, nil)
ok(t, err)
Expand All @@ -192,26 +275,14 @@ func TestOpen_Check(t *testing.T) {
db.Close()
}

// Ensure that the database returns an error if the file handle cannot be open.
func TestDB_Open_FileError(t *testing.T) {
path := tempfile()
defer os.Remove(path)

_, err := bolt.Open(path+"/youre-not-my-real-parent", 0666, nil)
assert(t, err.(*os.PathError) != nil, "")
equals(t, path+"/youre-not-my-real-parent", err.(*os.PathError).Path)
equals(t, "open", err.(*os.PathError).Op)
}

// Ensure that write errors to the meta file handler during initialization are returned.
func TestDB_Open_MetaInitWriteError(t *testing.T) {
func TestOpen_MetaInitWriteError(t *testing.T) {
t.Skip("pending")
}

// Ensure that a database that is too small returns an error.
func TestDB_Open_FileTooSmall(t *testing.T) {
func TestOpen_FileTooSmall(t *testing.T) {
path := tempfile()
defer os.Remove(path)

db, err := bolt.Open(path, 0666, nil)
ok(t, err)
Expand All @@ -235,7 +306,6 @@ func TestOpen_ReadOnly(t *testing.T) {
bucket, key, value := []byte(`bucket`), []byte(`key`), []byte(`value`)

path := tempfile()
defer os.Remove(path)

// Open in read-write mode.
db, err := bolt.Open(path, 0666, nil)
Expand Down

0 comments on commit 6d4e6a3

Please sign in to comment.