aboutsummaryrefslogtreecommitdiff
path: root/tests/tx_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tx_test.go')
-rw-r--r--tests/tx_test.go716
1 files changed, 0 insertions, 716 deletions
diff --git a/tests/tx_test.go b/tests/tx_test.go
deleted file mode 100644
index 2201e79..0000000
--- a/tests/tx_test.go
+++ /dev/null
@@ -1,716 +0,0 @@
-package bolt_test
-
-import (
- "bytes"
- "errors"
- "fmt"
- "log"
- "os"
- "testing"
-
- "github.com/boltdb/bolt"
-)
-
-// Ensure that committing a closed transaction returns an error.
-func TestTx_Commit_ErrTxClosed(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- tx, err := db.Begin(true)
- if err != nil {
- t.Fatal(err)
- }
-
- if _, err := tx.CreateBucket([]byte("foo")); err != nil {
- t.Fatal(err)
- }
-
- if err := tx.Commit(); err != nil {
- t.Fatal(err)
- }
-
- if err := tx.Commit(); err != bolt.ErrTxClosed {
- t.Fatalf("unexpected error: %s", err)
- }
-}
-
-// Ensure that rolling back a closed transaction returns an error.
-func TestTx_Rollback_ErrTxClosed(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- tx, err := db.Begin(true)
- if err != nil {
- t.Fatal(err)
- }
-
- if err := tx.Rollback(); err != nil {
- t.Fatal(err)
- }
- if err := tx.Rollback(); err != bolt.ErrTxClosed {
- t.Fatalf("unexpected error: %s", err)
- }
-}
-
-// Ensure that committing a read-only transaction returns an error.
-func TestTx_Commit_ErrTxNotWritable(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- tx, err := db.Begin(false)
- if err != nil {
- t.Fatal(err)
- }
- if err := tx.Commit(); err != bolt.ErrTxNotWritable {
- t.Fatal(err)
- }
-}
-
-// Ensure that a transaction can retrieve a cursor on the root bucket.
-func TestTx_Cursor(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
- t.Fatal(err)
- }
-
- if _, err := tx.CreateBucket([]byte("woojits")); err != nil {
- t.Fatal(err)
- }
-
- c := tx.Cursor()
- if k, v := c.First(); !bytes.Equal(k, []byte("widgets")) {
- t.Fatalf("unexpected key: %v", k)
- } else if v != nil {
- t.Fatalf("unexpected value: %v", v)
- }
-
- if k, v := c.Next(); !bytes.Equal(k, []byte("woojits")) {
- t.Fatalf("unexpected key: %v", k)
- } else if v != nil {
- t.Fatalf("unexpected value: %v", v)
- }
-
- if k, v := c.Next(); k != nil {
- t.Fatalf("unexpected key: %v", k)
- } else if v != nil {
- t.Fatalf("unexpected value: %v", k)
- }
-
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that creating a bucket with a read-only transaction returns an error.
-func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.View(func(tx *bolt.Tx) error {
- _, err := tx.CreateBucket([]byte("foo"))
- if err != bolt.ErrTxNotWritable {
- t.Fatalf("unexpected error: %s", err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that creating a bucket on a closed transaction returns an error.
-func TestTx_CreateBucket_ErrTxClosed(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- tx, err := db.Begin(true)
- if err != nil {
- t.Fatal(err)
- }
- if err := tx.Commit(); err != nil {
- t.Fatal(err)
- }
-
- if _, err := tx.CreateBucket([]byte("foo")); err != bolt.ErrTxClosed {
- t.Fatalf("unexpected error: %s", err)
- }
-}
-
-// Ensure that a Tx can retrieve a bucket.
-func TestTx_Bucket(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
- t.Fatal(err)
- }
- if tx.Bucket([]byte("widgets")) == nil {
- t.Fatal("expected bucket")
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that a Tx retrieving a non-existent key returns nil.
-func TestTx_Get_NotFound(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
-
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
- if b.Get([]byte("no_such_key")) != nil {
- t.Fatal("expected nil value")
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that a bucket can be created and retrieved.
-func TestTx_CreateBucket(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- // Create a bucket.
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- } else if b == nil {
- t.Fatal("expected bucket")
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- // Read the bucket through a separate transaction.
- if err := db.View(func(tx *bolt.Tx) error {
- if tx.Bucket([]byte("widgets")) == nil {
- t.Fatal("expected bucket")
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that a bucket can be created if it doesn't already exist.
-func TestTx_CreateBucketIfNotExists(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- // Create bucket.
- if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil {
- t.Fatal(err)
- } else if b == nil {
- t.Fatal("expected bucket")
- }
-
- // Create bucket again.
- if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil {
- t.Fatal(err)
- } else if b == nil {
- t.Fatal("expected bucket")
- }
-
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- // Read the bucket through a separate transaction.
- if err := db.View(func(tx *bolt.Tx) error {
- if tx.Bucket([]byte("widgets")) == nil {
- t.Fatal("expected bucket")
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure transaction returns an error if creating an unnamed bucket.
-func TestTx_CreateBucketIfNotExists_ErrBucketNameRequired(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucketIfNotExists([]byte{}); err != bolt.ErrBucketNameRequired {
- t.Fatalf("unexpected error: %s", err)
- }
-
- if _, err := tx.CreateBucketIfNotExists(nil); err != bolt.ErrBucketNameRequired {
- t.Fatalf("unexpected error: %s", err)
- }
-
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that a bucket cannot be created twice.
-func TestTx_CreateBucket_ErrBucketExists(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- // Create a bucket.
- if err := db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- // Create the same bucket again.
- if err := db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucket([]byte("widgets")); err != bolt.ErrBucketExists {
- t.Fatalf("unexpected error: %s", err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that a bucket is created with a non-blank name.
-func TestTx_CreateBucket_ErrBucketNameRequired(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- if _, err := tx.CreateBucket(nil); err != bolt.ErrBucketNameRequired {
- t.Fatalf("unexpected error: %s", err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that a bucket can be deleted.
-func TestTx_DeleteBucket(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- // Create a bucket and add a value.
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- // Delete the bucket and make sure we can't get the value.
- if err := db.Update(func(tx *bolt.Tx) error {
- if err := tx.DeleteBucket([]byte("widgets")); err != nil {
- t.Fatal(err)
- }
- if tx.Bucket([]byte("widgets")) != nil {
- t.Fatal("unexpected bucket")
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- if err := db.Update(func(tx *bolt.Tx) error {
- // Create the bucket again and make sure there's not a phantom value.
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if v := b.Get([]byte("foo")); v != nil {
- t.Fatalf("unexpected phantom value: %v", v)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that deleting a bucket on a closed transaction returns an error.
-func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- tx, err := db.Begin(true)
- if err != nil {
- t.Fatal(err)
- }
- if err := tx.Commit(); err != nil {
- t.Fatal(err)
- }
- if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxClosed {
- t.Fatalf("unexpected error: %s", err)
- }
-}
-
-// Ensure that deleting a bucket with a read-only transaction returns an error.
-func TestTx_DeleteBucket_ReadOnly(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.View(func(tx *bolt.Tx) error {
- if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxNotWritable {
- t.Fatalf("unexpected error: %s", err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that nothing happens when deleting a bucket that doesn't exist.
-func TestTx_DeleteBucket_NotFound(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- if err := tx.DeleteBucket([]byte("widgets")); err != bolt.ErrBucketNotFound {
- t.Fatalf("unexpected error: %s", err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that no error is returned when a tx.ForEach function does not return
-// an error.
-func TestTx_ForEach_NoError(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
-
- if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error {
- return nil
- }); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that an error is returned when a tx.ForEach function returns an error.
-func TestTx_ForEach_WithError(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
-
- marker := errors.New("marker")
- if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error {
- return marker
- }); err != marker {
- t.Fatalf("unexpected error: %s", err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-}
-
-// Ensure that Tx commit handlers are called after a transaction successfully commits.
-func TestTx_OnCommit(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- var x int
- if err := db.Update(func(tx *bolt.Tx) error {
- tx.OnCommit(func() { x += 1 })
- tx.OnCommit(func() { x += 2 })
- if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- } else if x != 3 {
- t.Fatalf("unexpected x: %d", x)
- }
-}
-
-// Ensure that Tx commit handlers are NOT called after a transaction rolls back.
-func TestTx_OnCommit_Rollback(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- var x int
- if err := db.Update(func(tx *bolt.Tx) error {
- tx.OnCommit(func() { x += 1 })
- tx.OnCommit(func() { x += 2 })
- if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
- t.Fatal(err)
- }
- return errors.New("rollback this commit")
- }); err == nil || err.Error() != "rollback this commit" {
- t.Fatalf("unexpected error: %s", err)
- } else if x != 0 {
- t.Fatalf("unexpected x: %d", x)
- }
-}
-
-// Ensure that the database can be copied to a file path.
-func TestTx_CopyFile(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
-
- path := tempfile()
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- if err := db.View(func(tx *bolt.Tx) error {
- return tx.CopyFile(path, 0600)
- }); err != nil {
- t.Fatal(err)
- }
-
- db2, err := bolt.Open(path, 0600, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- if err := db2.View(func(tx *bolt.Tx) error {
- if v := tx.Bucket([]byte("widgets")).Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) {
- t.Fatalf("unexpected value: %v", v)
- }
- if v := tx.Bucket([]byte("widgets")).Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) {
- t.Fatalf("unexpected value: %v", v)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- if err := db2.Close(); err != nil {
- t.Fatal(err)
- }
-}
-
-type failWriterError struct{}
-
-func (failWriterError) Error() string {
- return "error injected for tests"
-}
-
-type failWriter struct {
- // fail after this many bytes
- After int
-}
-
-func (f *failWriter) Write(p []byte) (n int, err error) {
- n = len(p)
- if n > f.After {
- n = f.After
- err = failWriterError{}
- }
- f.After -= n
- return n, err
-}
-
-// Ensure that Copy handles write errors right.
-func TestTx_CopyFile_Error_Meta(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- if err := db.View(func(tx *bolt.Tx) error {
- return tx.Copy(&failWriter{})
- }); err == nil || err.Error() != "meta 0 copy: error injected for tests" {
- t.Fatalf("unexpected error: %v", err)
- }
-}
-
-// Ensure that Copy handles write errors right.
-func TestTx_CopyFile_Error_Normal(t *testing.T) {
- db := MustOpenDB()
- defer db.MustClose()
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- t.Fatal(err)
- }
- if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
- t.Fatal(err)
- }
- return nil
- }); err != nil {
- t.Fatal(err)
- }
-
- if err := db.View(func(tx *bolt.Tx) error {
- return tx.Copy(&failWriter{3 * db.Info().PageSize})
- }); err == nil || err.Error() != "error injected for tests" {
- t.Fatalf("unexpected error: %v", err)
- }
-}
-
-func ExampleTx_Rollback() {
- // Open the database.
- db, err := bolt.Open(tempfile(), 0666, nil)
- if err != nil {
- log.Fatal(err)
- }
- defer os.Remove(db.Path())
-
- // Create a bucket.
- if err := db.Update(func(tx *bolt.Tx) error {
- _, err := tx.CreateBucket([]byte("widgets"))
- return err
- }); err != nil {
- log.Fatal(err)
- }
-
- // Set a value for a key.
- if err := db.Update(func(tx *bolt.Tx) error {
- return tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar"))
- }); err != nil {
- log.Fatal(err)
- }
-
- // Update the key but rollback the transaction so it never saves.
- tx, err := db.Begin(true)
- if err != nil {
- log.Fatal(err)
- }
- b := tx.Bucket([]byte("widgets"))
- if err := b.Put([]byte("foo"), []byte("baz")); err != nil {
- log.Fatal(err)
- }
- if err := tx.Rollback(); err != nil {
- log.Fatal(err)
- }
-
- // Ensure that our original value is still set.
- if err := db.View(func(tx *bolt.Tx) error {
- value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
- fmt.Printf("The value for 'foo' is still: %s\n", value)
- return nil
- }); err != nil {
- log.Fatal(err)
- }
-
- // Close database to release file lock.
- if err := db.Close(); err != nil {
- log.Fatal(err)
- }
-
- // Output:
- // The value for 'foo' is still: bar
-}
-
-func ExampleTx_CopyFile() {
- // Open the database.
- db, err := bolt.Open(tempfile(), 0666, nil)
- if err != nil {
- log.Fatal(err)
- }
- defer os.Remove(db.Path())
-
- // Create a bucket and a key.
- if err := db.Update(func(tx *bolt.Tx) error {
- b, err := tx.CreateBucket([]byte("widgets"))
- if err != nil {
- return err
- }
- if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
- return err
- }
- return nil
- }); err != nil {
- log.Fatal(err)
- }
-
- // Copy the database to another file.
- toFile := tempfile()
- if err := db.View(func(tx *bolt.Tx) error {
- return tx.CopyFile(toFile, 0666)
- }); err != nil {
- log.Fatal(err)
- }
- defer os.Remove(toFile)
-
- // Open the cloned database.
- db2, err := bolt.Open(toFile, 0666, nil)
- if err != nil {
- log.Fatal(err)
- }
-
- // Ensure that the key exists in the copy.
- if err := db2.View(func(tx *bolt.Tx) error {
- value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
- fmt.Printf("The value for 'foo' in the clone is: %s\n", value)
- return nil
- }); err != nil {
- log.Fatal(err)
- }
-
- // Close database to release file lock.
- if err := db.Close(); err != nil {
- log.Fatal(err)
- }
-
- if err := db2.Close(); err != nil {
- log.Fatal(err)
- }
-
- // Output:
- // The value for 'foo' in the clone is: bar
-}