aboutsummaryrefslogtreecommitdiff
path: root/tx_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'tx_test.go')
-rw-r--r--tx_test.go225
1 files changed, 140 insertions, 85 deletions
diff --git a/tx_test.go b/tx_test.go
index d3ad131..afdbb02 100644
--- a/tx_test.go
+++ b/tx_test.go
@@ -16,15 +16,18 @@ import (
// Ensure that the database can retrieve a list of buckets.
func TestTxBuckets(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("foo")
- db.CreateBucket("bar")
- db.CreateBucket("baz")
- buckets, err := db.Buckets()
- if assert.NoError(t, err) && assert.Equal(t, len(buckets), 3) {
- assert.Equal(t, buckets[0].Name(), "bar")
- assert.Equal(t, buckets[1].Name(), "baz")
- assert.Equal(t, buckets[2].Name(), "foo")
- }
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("foo")
+ tx.CreateBucket("bar")
+ tx.CreateBucket("baz")
+ buckets := tx.Buckets()
+ if assert.Equal(t, len(buckets), 3) {
+ assert.Equal(t, buckets[0].Name(), "bar")
+ assert.Equal(t, buckets[1].Name(), "baz")
+ assert.Equal(t, buckets[2].Name(), "foo")
+ }
+ return nil
+ })
})
}
@@ -39,33 +42,40 @@ func TestTxCreateBucketReadOnly(t *testing.T) {
}
// Ensure that a Tx can retrieve a bucket.
-func TestTxBucketMissing(t *testing.T) {
+func TestTxBucket(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
- b, err := db.Bucket("widgets")
- assert.NoError(t, err)
- if assert.NotNil(t, b) {
- assert.Equal(t, "widgets", b.Name())
- }
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ b := tx.Bucket("widgets")
+ if assert.NotNil(t, b) {
+ assert.Equal(t, "widgets", b.Name())
+ }
+ return nil
+ })
})
}
// Ensure that a Tx retrieving a non-existent key returns nil.
func TestTxGetMissing(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
- db.Put("widgets", []byte("foo"), []byte("bar"))
- value, err := db.Get("widgets", []byte("no_such_key"))
- assert.NoError(t, err)
- assert.Nil(t, value)
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
+ value := tx.Bucket("widgets").Get([]byte("no_such_key"))
+ assert.Nil(t, value)
+ return nil
+ })
})
}
// Ensure that retrieving all buckets returns writable buckets.
func TestTxWritableBuckets(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
- db.CreateBucket("woojits")
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ tx.CreateBucket("woojits")
+ return nil
+ })
db.Do(func(tx *Tx) error {
buckets := tx.Buckets()
assert.Equal(t, len(buckets), 2)
@@ -75,10 +85,11 @@ func TestTxWritableBuckets(t *testing.T) {
buckets[1].Put([]byte("bar"), []byte("0001"))
return nil
})
- v, _ := db.Get("widgets", []byte("foo"))
- assert.Equal(t, v, []byte("0000"))
- v, _ = db.Get("woojits", []byte("bar"))
- assert.Equal(t, v, []byte("0001"))
+ db.With(func(tx *Tx) error {
+ assert.Equal(t, []byte("0000"), tx.Bucket("widgets").Get([]byte("foo")))
+ assert.Equal(t, []byte("0001"), tx.Bucket("woojits").Get([]byte("bar")))
+ return nil
+ })
})
}
@@ -86,27 +97,36 @@ func TestTxWritableBuckets(t *testing.T) {
func TestTxCreateBucket(t *testing.T) {
withOpenDB(func(db *DB, path string) {
// Create a bucket.
- err := db.CreateBucket("widgets")
- assert.NoError(t, err)
+ db.Do(func(tx *Tx) error {
+ assert.NoError(t, tx.CreateBucket("widgets"))
+ return nil
+ })
// Read the bucket through a separate transaction.
- b, err := db.Bucket("widgets")
- assert.NotNil(t, b)
- assert.NoError(t, err)
+ db.With(func(tx *Tx) error {
+ b := tx.Bucket("widgets")
+ assert.NotNil(t, b)
+ return nil
+ })
})
}
// Ensure that a bucket can be created if it doesn't already exist.
func TestTxCreateBucketIfNotExists(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- assert.NoError(t, db.CreateBucketIfNotExists("widgets"))
- assert.NoError(t, db.CreateBucketIfNotExists("widgets"))
- assert.Equal(t, db.CreateBucketIfNotExists(""), ErrBucketNameRequired)
+ db.Do(func(tx *Tx) error {
+ assert.NoError(t, tx.CreateBucketIfNotExists("widgets"))
+ assert.NoError(t, tx.CreateBucketIfNotExists("widgets"))
+ assert.Equal(t, tx.CreateBucketIfNotExists(""), ErrBucketNameRequired)
+ return nil
+ })
// Read the bucket through a separate transaction.
- b, err := db.Bucket("widgets")
- assert.NotNil(t, b)
- assert.NoError(t, err)
+ db.With(func(tx *Tx) error {
+ b := tx.Bucket("widgets")
+ assert.NotNil(t, b)
+ return nil
+ })
})
}
@@ -114,31 +134,37 @@ func TestTxCreateBucketIfNotExists(t *testing.T) {
func TestTxRecreateBucket(t *testing.T) {
withOpenDB(func(db *DB, path string) {
// Create a bucket.
- err := db.CreateBucket("widgets")
- assert.NoError(t, err)
+ db.Do(func(tx *Tx) error {
+ assert.NoError(t, tx.CreateBucket("widgets"))
+ return nil
+ })
// Create the same bucket again.
- err = db.CreateBucket("widgets")
- assert.Equal(t, err, ErrBucketExists)
+ db.Do(func(tx *Tx) error {
+ assert.Equal(t, ErrBucketExists, tx.CreateBucket("widgets"))
+ return nil
+ })
})
}
// Ensure that a bucket is created with a non-blank name.
func TestTxCreateBucketWithoutName(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- err := db.CreateBucket("")
- assert.Equal(t, err, ErrBucketNameRequired)
+ db.Do(func(tx *Tx) error {
+ assert.Equal(t, ErrBucketNameRequired, tx.CreateBucket(""))
+ return nil
+ })
})
}
// Ensure that a bucket name is not too long.
func TestTxCreateBucketWithLongName(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- err := db.CreateBucket(strings.Repeat("X", 255))
- assert.NoError(t, err)
-
- err = db.CreateBucket(strings.Repeat("X", 256))
- assert.Equal(t, err, ErrBucketNameTooLarge)
+ db.Do(func(tx *Tx) error {
+ assert.NoError(t, tx.CreateBucket(strings.Repeat("X", 255)))
+ assert.Equal(t, ErrBucketNameTooLarge, tx.CreateBucket(strings.Repeat("X", 256)))
+ return nil
+ })
})
}
@@ -146,25 +172,35 @@ func TestTxCreateBucketWithLongName(t *testing.T) {
func TestTxDeleteBucket(t *testing.T) {
withOpenDB(func(db *DB, path string) {
// Create a bucket and add a value.
- db.CreateBucket("widgets")
- db.Put("widgets", []byte("foo"), []byte("bar"))
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ tx.Bucket("widgets").Put([]byte("foo"), []byte("bar"))
+ return nil
+ })
- b, _ := db.Bucket("widgets")
+ // Save root page id.
+ var root pgid
+ db.With(func(tx *Tx) error {
+ root = tx.Bucket("widgets").root
+ return nil
+ })
// Delete the bucket and make sure we can't get the value.
- assert.NoError(t, db.DeleteBucket("widgets"))
- value, err := db.Get("widgets", []byte("foo"))
- assert.Equal(t, err, ErrBucketNotFound)
- assert.Nil(t, value)
-
- // Verify that the bucket's page is free.
- assert.Equal(t, db.freelist.all(), []pgid{b.root})
-
- // Create the bucket again and make sure there's not a phantom value.
- assert.NoError(t, db.CreateBucket("widgets"))
- value, err = db.Get("widgets", []byte("foo"))
- assert.NoError(t, err)
- assert.Nil(t, value)
+ db.Do(func(tx *Tx) error {
+ assert.NoError(t, tx.DeleteBucket("widgets"))
+ assert.Nil(t, tx.Bucket("widgets"))
+ return nil
+ })
+
+ db.Do(func(tx *Tx) error {
+ // Verify that the bucket's page is free.
+ assert.Equal(t, []pgid{root}, db.freelist.all())
+
+ // Create the bucket again and make sure there's not a phantom value.
+ assert.NoError(t, tx.CreateBucket("widgets"))
+ assert.Nil(t, tx.Bucket("widgets").Get([]byte("foo")))
+ return nil
+ })
})
}
@@ -181,15 +217,19 @@ func TestTxDeleteBucketReadOnly(t *testing.T) {
// Ensure that an error is returned when deleting from a bucket that doesn't exist.
func TestTxDeleteBucketNotFound(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- err := db.DeleteBucket("widgets")
- assert.Equal(t, err, ErrBucketNotFound)
+ db.Do(func(tx *Tx) error {
+ assert.Equal(t, ErrBucketNotFound, tx.DeleteBucket("widgets"))
+ return nil
+ })
})
}
// Ensure that a Tx cursor can iterate over an empty bucket without error.
func TestTxCursorEmptyBucket(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
+ db.Do(func(tx *Tx) error {
+ return tx.CreateBucket("widgets")
+ })
db.With(func(tx *Tx) error {
c := tx.Bucket("widgets").Cursor()
k, v := c.First()
@@ -203,7 +243,9 @@ func TestTxCursorEmptyBucket(t *testing.T) {
// Ensure that a Tx cursor can reverse iterate over an empty bucket without error.
func TestCursorEmptyBucketReverse(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
+ db.Do(func(tx *Tx) error {
+ return tx.CreateBucket("widgets")
+ })
db.With(func(tx *Tx) error {
c := tx.Bucket("widgets").Cursor()
k, v := c.Last()
@@ -217,10 +259,13 @@ func TestCursorEmptyBucketReverse(t *testing.T) {
// Ensure that a Tx cursor can iterate over a single root with a couple elements.
func TestTxCursorLeafRoot(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
- db.Put("widgets", []byte("baz"), []byte{})
- db.Put("widgets", []byte("foo"), []byte{0})
- db.Put("widgets", []byte("bar"), []byte{1})
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ tx.Bucket("widgets").Put([]byte("baz"), []byte{})
+ tx.Bucket("widgets").Put([]byte("foo"), []byte{0})
+ tx.Bucket("widgets").Put([]byte("bar"), []byte{1})
+ return nil
+ })
tx, _ := db.Tx()
c := tx.Bucket("widgets").Cursor()
@@ -251,10 +296,13 @@ func TestTxCursorLeafRoot(t *testing.T) {
// Ensure that a Tx cursor can iterate in reverse over a single root with a couple elements.
func TestTxCursorLeafRootReverse(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
- db.Put("widgets", []byte("baz"), []byte{})
- db.Put("widgets", []byte("foo"), []byte{0})
- db.Put("widgets", []byte("bar"), []byte{1})
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ tx.Bucket("widgets").Put([]byte("baz"), []byte{})
+ tx.Bucket("widgets").Put([]byte("foo"), []byte{0})
+ tx.Bucket("widgets").Put([]byte("bar"), []byte{1})
+ return nil
+ })
tx, _ := db.Tx()
c := tx.Bucket("widgets").Cursor()
@@ -285,9 +333,12 @@ func TestTxCursorLeafRootReverse(t *testing.T) {
// Ensure that a Tx cursor can restart from the beginning.
func TestTxCursorRestart(t *testing.T) {
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
- db.Put("widgets", []byte("bar"), []byte{})
- db.Put("widgets", []byte("foo"), []byte{})
+ db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
+ tx.Bucket("widgets").Put([]byte("bar"), []byte{})
+ tx.Bucket("widgets").Put([]byte("foo"), []byte{})
+ return nil
+ })
tx, _ := db.Tx()
c := tx.Bucket("widgets").Cursor()
@@ -317,8 +368,8 @@ func TestTxCursorIterate(t *testing.T) {
f := func(items testdata) bool {
withOpenDB(func(db *DB, path string) {
// Bulk insert all values.
- db.CreateBucket("widgets")
tx, _ := db.RWTx()
+ tx.CreateBucket("widgets")
b := tx.Bucket("widgets")
for _, item := range items {
assert.NoError(t, b.Put(item.Key, item.Value))
@@ -358,8 +409,8 @@ func TestTxCursorIterateReverse(t *testing.T) {
f := func(items testdata) bool {
withOpenDB(func(db *DB, path string) {
// Bulk insert all values.
- db.CreateBucket("widgets")
tx, _ := db.RWTx()
+ tx.CreateBucket("widgets")
b := tx.Bucket("widgets")
for _, item := range items {
assert.NoError(t, b.Put(item.Key, item.Value))
@@ -397,8 +448,8 @@ func BenchmarkTxCursor(b *testing.B) {
withOpenDB(func(db *DB, path string) {
// Write data to bucket.
- db.CreateBucket("widgets")
db.Do(func(tx *Tx) error {
+ tx.CreateBucket("widgets")
bucket := tx.Bucket("widgets")
for i := 0; i < b.N; i++ {
bucket.Put([]byte(strconv.Itoa(indexes[i])), value)
@@ -427,7 +478,9 @@ func BenchmarkTxPutRandom(b *testing.B) {
indexes := rand.Perm(b.N)
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
+ db.Do(func(tx *Tx) error {
+ return tx.CreateBucket("widgets")
+ })
var tx *Tx
var bucket *Bucket
for i := 0; i < b.N; i++ {
@@ -448,7 +501,9 @@ func BenchmarkTxPutRandom(b *testing.B) {
func BenchmarkTxPutSequential(b *testing.B) {
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
- db.CreateBucket("widgets")
+ db.Do(func(tx *Tx) error {
+ return tx.CreateBucket("widgets")
+ })
db.Do(func(tx *Tx) error {
bucket := tx.Bucket("widgets")
for i := 0; i < b.N; i++ {