Remove withTempPath() helper.

pull/34/head
Ben Johnson 2014-07-25 23:14:17 -06:00
parent d021755f07
commit 06222e06de
1 changed files with 129 additions and 126 deletions

View File

@ -28,13 +28,13 @@ func TestOpen_BadPath(t *testing.T) {
// Ensure that a database can be opened without error. // Ensure that a database can be opened without error.
func TestOpen(t *testing.T) { func TestOpen(t *testing.T) {
withTempPath(func(path string) { path := tempfile()
db, err := Open(path, 0666, nil) defer os.Remove(path)
assert.NotNil(t, db) db, err := Open(path, 0666, nil)
assert.NoError(t, err) assert.NotNil(t, db)
assert.Equal(t, db.Path(), path) assert.NoError(t, err)
assert.NoError(t, db.Close()) assert.Equal(t, db.Path(), path)
}) assert.NoError(t, db.Close())
} }
// Ensure that opening an already open database file will timeout. // Ensure that opening an already open database file will timeout.
@ -42,21 +42,23 @@ func TestOpen_Timeout(t *testing.T) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
t.Skip("timeout not supported on windows") t.Skip("timeout not supported on windows")
} }
withTempPath(func(path string) {
// Open a data file.
db0, err := Open(path, 0666, nil)
assert.NotNil(t, db0)
assert.NoError(t, err)
// Attempt to open the database again. path := tempfile()
start := time.Now() defer os.Remove(path)
db1, err := Open(path, 0666, &Options{Timeout: 100 * time.Millisecond})
assert.Nil(t, db1)
assert.Equal(t, ErrTimeout, err)
assert.True(t, time.Since(start) > 100*time.Millisecond)
db0.Close() // Open a data file.
}) db0, err := Open(path, 0666, nil)
assert.NotNil(t, db0)
assert.NoError(t, err)
// Attempt to open the database again.
start := time.Now()
db1, err := Open(path, 0666, &Options{Timeout: 100 * time.Millisecond})
assert.Nil(t, db1)
assert.Equal(t, ErrTimeout, err)
assert.True(t, time.Since(start) > 100*time.Millisecond)
db0.Close()
} }
// Ensure that opening an already open database file will wait until its closed. // Ensure that opening an already open database file will wait until its closed.
@ -64,48 +66,52 @@ func TestOpen_Wait(t *testing.T) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
t.Skip("timeout not supported on windows") t.Skip("timeout not supported on windows")
} }
withTempPath(func(path string) {
// Open a data file.
db0, err := Open(path, 0666, nil)
assert.NotNil(t, db0)
assert.NoError(t, err)
// Close it in just a bit. path := tempfile()
time.AfterFunc(100*time.Millisecond, func() { db0.Close() }) defer os.Remove(path)
// Attempt to open the database again. // Open a data file.
start := time.Now() db0, err := Open(path, 0666, nil)
db1, err := Open(path, 0666, &Options{Timeout: 200 * time.Millisecond}) assert.NotNil(t, db0)
assert.NotNil(t, db1) assert.NoError(t, err)
assert.NoError(t, err)
assert.True(t, time.Since(start) > 100*time.Millisecond) // Close it in just a bit.
}) time.AfterFunc(100*time.Millisecond, func() { db0.Close() })
// Attempt to open the database again.
start := time.Now()
db1, err := Open(path, 0666, &Options{Timeout: 200 * time.Millisecond})
assert.NotNil(t, db1)
assert.NoError(t, err)
assert.True(t, time.Since(start) > 100*time.Millisecond)
} }
// Ensure that a re-opened database is consistent. // Ensure that a re-opened database is consistent.
func TestOpen_Check(t *testing.T) { func TestOpen_Check(t *testing.T) {
withTempPath(func(path string) { path := tempfile()
db, err := Open(path, 0666, nil) defer os.Remove(path)
assert.NoError(t, err)
assert.NoError(t, db.View(func(tx *Tx) error { return <-tx.Check() }))
db.Close()
db, err = Open(path, 0666, nil) db, err := Open(path, 0666, nil)
assert.NoError(t, err) assert.NoError(t, err)
assert.NoError(t, db.View(func(tx *Tx) error { return <-tx.Check() })) assert.NoError(t, db.View(func(tx *Tx) error { return <-tx.Check() }))
db.Close() db.Close()
})
db, err = Open(path, 0666, nil)
assert.NoError(t, err)
assert.NoError(t, db.View(func(tx *Tx) error { return <-tx.Check() }))
db.Close()
} }
// Ensure that the database returns an error if the file handle cannot be open. // Ensure that the database returns an error if the file handle cannot be open.
func TestDB_Open_FileError(t *testing.T) { func TestDB_Open_FileError(t *testing.T) {
withTempPath(func(path string) { path := tempfile()
_, err := Open(path+"/youre-not-my-real-parent", 0666, nil) defer os.Remove(path)
if err, _ := err.(*os.PathError); assert.Error(t, err) {
assert.Equal(t, path+"/youre-not-my-real-parent", err.Path) _, err := Open(path+"/youre-not-my-real-parent", 0666, nil)
assert.Equal(t, "open", err.Op) if err, _ := err.(*os.PathError); assert.Error(t, err) {
} assert.Equal(t, path+"/youre-not-my-real-parent", err.Path)
}) assert.Equal(t, "open", err.Op)
}
} }
// Ensure that write errors to the meta file handler during initialization are returned. // Ensure that write errors to the meta file handler during initialization are returned.
@ -115,75 +121,78 @@ func TestDB_Open_MetaInitWriteError(t *testing.T) {
// Ensure that a database that is too small returns an error. // Ensure that a database that is too small returns an error.
func TestDB_Open_FileTooSmall(t *testing.T) { func TestDB_Open_FileTooSmall(t *testing.T) {
withTempPath(func(path string) { path := tempfile()
db, err := Open(path, 0666, nil) defer os.Remove(path)
assert.NoError(t, err)
db.Close()
// corrupt the database db, err := Open(path, 0666, nil)
assert.NoError(t, os.Truncate(path, int64(os.Getpagesize()))) assert.NoError(t, err)
db.Close()
db, err = Open(path, 0666, nil) // corrupt the database
assert.Equal(t, errors.New("file size too small"), err) assert.NoError(t, os.Truncate(path, int64(os.Getpagesize())))
})
db, err = Open(path, 0666, nil)
assert.Equal(t, errors.New("file size too small"), err)
} }
// Ensure that corrupt meta0 page errors get returned. // Ensure that corrupt meta0 page errors get returned.
func TestDB_Open_CorruptMeta0(t *testing.T) { func TestDB_Open_CorruptMeta0(t *testing.T) {
withTempPath(func(path string) { var m meta
var m meta m.magic = magic
m.magic = magic m.version = version
m.version = version m.pageSize = 0x8000
m.pageSize = 0x8000
// Create a file with bad magic. path := tempfile()
b := make([]byte, 0x10000) defer os.Remove(path)
p0, p1 := (*page)(unsafe.Pointer(&b[0x0000])), (*page)(unsafe.Pointer(&b[0x8000]))
p0.meta().magic = 0
p0.meta().version = version
p1.meta().magic = magic
p1.meta().version = version
err := ioutil.WriteFile(path, b, 0666)
assert.NoError(t, err)
// Open the database. // Create a file with bad magic.
_, err = Open(path, 0666, nil) b := make([]byte, 0x10000)
assert.Equal(t, err, errors.New("meta0 error: invalid database")) p0, p1 := (*page)(unsafe.Pointer(&b[0x0000])), (*page)(unsafe.Pointer(&b[0x8000]))
}) p0.meta().magic = 0
p0.meta().version = version
p1.meta().magic = magic
p1.meta().version = version
err := ioutil.WriteFile(path, b, 0666)
assert.NoError(t, err)
// Open the database.
_, err = Open(path, 0666, nil)
assert.Equal(t, err, errors.New("meta0 error: invalid database"))
} }
// Ensure that a corrupt meta page checksum causes the open to fail. // Ensure that a corrupt meta page checksum causes the open to fail.
func TestDB_Open_MetaChecksumError(t *testing.T) { func TestDB_Open_MetaChecksumError(t *testing.T) {
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
withTempPath(func(path string) { path := tempfile()
db, err := Open(path, 0600, nil) defer os.Remove(path)
pageSize := db.pageSize
db.Update(func(tx *Tx) error {
_, err := tx.CreateBucket([]byte("widgets"))
return err
})
db.Update(func(tx *Tx) error {
_, err := tx.CreateBucket([]byte("woojits"))
return err
})
db.Close()
// Change a single byte in the meta page. db, err := Open(path, 0600, nil)
f, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600) pageSize := db.pageSize
f.WriteAt([]byte{1}, int64((i*pageSize)+(pageHeaderSize+12))) db.Update(func(tx *Tx) error {
f.Sync() _, err := tx.CreateBucket([]byte("widgets"))
f.Close() return err
// Reopen the database.
_, err = Open(path, 0600, nil)
if assert.Error(t, err) {
if i == 0 {
assert.Equal(t, "meta0 error: checksum error", err.Error())
} else {
assert.Equal(t, "meta1 error: checksum error", err.Error())
}
}
}) })
db.Update(func(tx *Tx) error {
_, err := tx.CreateBucket([]byte("woojits"))
return err
})
db.Close()
// Change a single byte in the meta page.
f, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600)
f.WriteAt([]byte{1}, int64((i*pageSize)+(pageHeaderSize+12)))
f.Sync()
f.Close()
// Reopen the database.
_, err = Open(path, 0600, nil)
if assert.Error(t, err) {
if i == 0 {
assert.Equal(t, "meta0 error: checksum error", err.Error())
} else {
assert.Equal(t, "meta1 error: checksum error", err.Error())
}
}
} }
} }
@ -579,31 +588,25 @@ func tempfile() string {
return f.Name() return f.Name()
} }
// withTempPath executes a function with a database reference.
func withTempPath(fn func(string)) {
path := tempfile()
defer os.RemoveAll(path)
fn(path)
}
// withOpenDB executes a function with an already opened database. // withOpenDB executes a function with an already opened database.
func withOpenDB(fn func(*DB, string)) { func withOpenDB(fn func(*DB, string)) {
withTempPath(func(path string) { path := tempfile()
db, err := Open(path, 0666, nil) defer os.Remove(path)
if err != nil {
panic("cannot open db: " + err.Error())
}
defer db.Close()
fn(db, path)
// Log statistics. db, err := Open(path, 0666, nil)
if *statsFlag { if err != nil {
logStats(db) panic("cannot open db: " + err.Error())
} }
defer db.Close()
fn(db, path)
// Check database consistency after every test. // Log statistics.
mustCheck(db) if *statsFlag {
}) logStats(db)
}
// Check database consistency after every test.
mustCheck(db)
} }
// mustCheck runs a consistency check on the database and panics if any errors are found. // mustCheck runs a consistency check on the database and panics if any errors are found.