diff options
Diffstat (limited to 'tx_test.go')
-rw-r--r-- | tx_test.go | 225 |
1 files changed, 140 insertions, 85 deletions
@@ -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++ { |