diff options
author | Ben Johnson <benbjohnson@yahoo.com> | 2014-02-22 22:54:54 -0700 |
---|---|---|
committer | Ben Johnson <benbjohnson@yahoo.com> | 2014-02-22 22:54:54 -0700 |
commit | 3b2fd8f2d3e376fa7a3f3b2ba665fcd4a5b5bb15 (patch) | |
tree | a2b7de98448c4ddd427449dfe85695fa5c7c9c22 /transaction_test.go | |
parent | Merge pull request #50 from benbjohnson/api (diff) | |
download | dedo-3b2fd8f2d3e376fa7a3f3b2ba665fcd4a5b5bb15.tar.gz dedo-3b2fd8f2d3e376fa7a3f3b2ba665fcd4a5b5bb15.tar.xz |
Revert "Refactor Transaction/Bucket API."
This reverts commit 1ad2b99f281d587b767b36f886401e81d17915a9.
Diffstat (limited to 'transaction_test.go')
-rw-r--r-- | transaction_test.go | 336 |
1 files changed, 38 insertions, 298 deletions
diff --git a/transaction_test.go b/transaction_test.go index 880b299..4a7170c 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -1,11 +1,9 @@ package bolt import ( - "bytes" "fmt" "os" "sort" - "strings" "testing" "testing/quick" @@ -55,11 +53,24 @@ func TestTransactionCursorEmptyBucket(t *testing.T) { withOpenDB(func(db *DB, path string) { db.CreateBucket("widgets") txn, _ := db.Transaction() - c := txn.Bucket("widgets").Cursor() + c, err := txn.Cursor("widgets") + assert.NoError(t, err) k, v := c.First() assert.Nil(t, k) assert.Nil(t, v) - txn.Rollback() + txn.Close() + }) +} + +// Ensure that a Transaction returns a nil when a bucket doesn't exist. +func TestTransactionCursorMissingBucket(t *testing.T) { + withOpenDB(func(db *DB, path string) { + db.CreateBucket("widgets") + txn, _ := db.Transaction() + c, err := txn.Cursor("woojits") + assert.Nil(t, c) + assert.Equal(t, err, ErrBucketNotFound) + txn.Close() }) } @@ -71,7 +82,8 @@ func TestTransactionCursorLeafRoot(t *testing.T) { db.Put("widgets", []byte("foo"), []byte{0}) db.Put("widgets", []byte("bar"), []byte{1}) txn, _ := db.Transaction() - c := txn.Bucket("widgets").Cursor() + c, err := txn.Cursor("widgets") + assert.NoError(t, err) k, v := c.First() assert.Equal(t, string(k), "bar") @@ -93,7 +105,7 @@ func TestTransactionCursorLeafRoot(t *testing.T) { assert.Nil(t, k) assert.Nil(t, v) - txn.Rollback() + txn.Close() }) } @@ -105,7 +117,8 @@ func TestTransactionCursorLeafRootReverse(t *testing.T) { db.Put("widgets", []byte("foo"), []byte{0}) db.Put("widgets", []byte("bar"), []byte{1}) txn, _ := db.Transaction() - c := txn.Bucket("widgets").Cursor() + c, err := txn.Cursor("widgets") + assert.NoError(t, err) k, v := c.Last() assert.Equal(t, string(k), "foo") @@ -127,7 +140,7 @@ func TestTransactionCursorLeafRootReverse(t *testing.T) { assert.Nil(t, k) assert.Nil(t, v) - txn.Rollback() + txn.Close() }) } @@ -139,7 +152,8 @@ func TestTransactionCursorRestart(t *testing.T) { db.Put("widgets", []byte("foo"), []byte{}) txn, _ := db.Transaction() - c := txn.Bucket("widgets").Cursor() + c, err := txn.Cursor("widgets") + assert.NoError(t, err) k, _ := c.First() assert.Equal(t, string(k), "bar") @@ -153,7 +167,7 @@ func TestTransactionCursorRestart(t *testing.T) { k, _ = c.Next() assert.Equal(t, string(k), "foo") - txn.Rollback() + txn.Close() }) } @@ -163,27 +177,27 @@ func TestTransactionCursorIterate(t *testing.T) { withOpenDB(func(db *DB, path string) { // Bulk insert all values. db.CreateBucket("widgets") - txn, _ := db.RWTransaction() - b := txn.Bucket("widgets") + rwtxn, _ := db.RWTransaction() for _, item := range items { - assert.NoError(t, b.Put(item.Key, item.Value)) + assert.NoError(t, rwtxn.Put("widgets", item.Key, item.Value)) } - assert.NoError(t, txn.Commit()) + assert.NoError(t, rwtxn.Commit()) // Sort test data. sort.Sort(items) // Iterate over all items and check consistency. var index = 0 - txn, _ = db.Transaction() - c := txn.Bucket("widgets").Cursor() + txn, _ := db.Transaction() + c, err := txn.Cursor("widgets") + assert.NoError(t, err) for k, v := c.First(); k != nil && index < len(items); k, v = c.Next() { assert.Equal(t, k, items[index].Key) assert.Equal(t, v, items[index].Value) index++ } assert.Equal(t, len(items), index) - txn.Rollback() + txn.Close() }) fmt.Fprint(os.Stderr, ".") return true @@ -200,301 +214,27 @@ func TestTransactionCursorIterateReverse(t *testing.T) { withOpenDB(func(db *DB, path string) { // Bulk insert all values. db.CreateBucket("widgets") - txn, _ := db.RWTransaction() - b := txn.Bucket("widgets") + rwtxn, _ := db.RWTransaction() for _, item := range items { - assert.NoError(t, b.Put(item.Key, item.Value)) + assert.NoError(t, rwtxn.Put("widgets", item.Key, item.Value)) } - assert.NoError(t, txn.Commit()) + assert.NoError(t, rwtxn.Commit()) // Sort test data. sort.Sort(revtestdata(items)) // Iterate over all items and check consistency. var index = 0 - txn, _ = db.Transaction() - c := txn.Bucket("widgets").Cursor() + txn, _ := db.Transaction() + c, err := txn.Cursor("widgets") + assert.NoError(t, err) for k, v := c.Last(); k != nil && index < len(items); k, v = c.Prev() { assert.Equal(t, k, items[index].Key) assert.Equal(t, v, items[index].Value) index++ } assert.Equal(t, len(items), index) - txn.Rollback() - }) - fmt.Fprint(os.Stderr, ".") - return true - } - if err := quick.Check(f, qconfig()); err != nil { - t.Error(err) - } - fmt.Fprint(os.Stderr, "\n") -} - -// Ensure that a bucket can be created and retrieved. -func TestTransactionCreateBucket(t *testing.T) { - withOpenDB(func(db *DB, path string) { - // Create a bucket. - err := db.CreateBucket("widgets") - assert.NoError(t, err) - - // Read the bucket through a separate transaction. - b, err := db.Bucket("widgets") - assert.NotNil(t, b) - assert.NoError(t, err) - }) -} - -// Ensure that a bucket can be created if it doesn't already exist. -func TestTransactionCreateBucketIfNotExists(t *testing.T) { - withOpenDB(func(db *DB, path string) { - assert.NoError(t, db.CreateBucketIfNotExists("widgets")) - assert.NoError(t, db.CreateBucketIfNotExists("widgets")) - - // Read the bucket through a separate transaction. - b, err := db.Bucket("widgets") - assert.NotNil(t, b) - assert.NoError(t, err) - }) -} - -// Ensure that a bucket cannot be created twice. -func TestTransactionRecreateBucket(t *testing.T) { - withOpenDB(func(db *DB, path string) { - // Create a bucket. - err := db.CreateBucket("widgets") - assert.NoError(t, err) - - // Create the same bucket again. - err = db.CreateBucket("widgets") - assert.Equal(t, err, ErrBucketExists) - }) -} - -// Ensure that a bucket is created with a non-blank name. -func TestTransactionCreateBucketWithoutName(t *testing.T) { - withOpenDB(func(db *DB, path string) { - err := db.CreateBucket("") - assert.Equal(t, err, ErrBucketNameRequired) - }) -} - -// Ensure that a bucket name is not too long. -func TestTransactionCreateBucketWithLongName(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) - }) -} - -// Ensure that a bucket can be deleted. -func TestTransactionDeleteBucket(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")) - - // 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) - - // 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) - }) -} - -// Ensure that a bucket can return an autoincrementing sequence. -func TestTransactionNextSequence(t *testing.T) { - withOpenDB(func(db *DB, path string) { - db.CreateBucket("widgets") - db.CreateBucket("woojits") - - // Make sure sequence increments. - seq, err := db.NextSequence("widgets") - assert.NoError(t, err) - assert.Equal(t, seq, 1) - seq, err = db.NextSequence("widgets") - assert.NoError(t, err) - assert.Equal(t, seq, 2) - - // Buckets should be separate. - seq, err = db.NextSequence("woojits") - assert.NoError(t, err) - assert.Equal(t, seq, 1) - - // Missing buckets return an error. - seq, err = db.NextSequence("no_such_bucket") - assert.Equal(t, err, ErrBucketNotFound) - assert.Equal(t, seq, 0) - }) -} - -// Ensure that incrementing past the maximum sequence number will return an error. -func TestTransactionNextSequenceOverflow(t *testing.T) { - withOpenDB(func(db *DB, path string) { - db.CreateBucket("widgets") - db.Do(func(txn *Transaction) error { - b := txn.Bucket("widgets") - b.bucket.sequence = uint64(maxInt) - seq, err := b.NextSequence() - assert.Equal(t, err, ErrSequenceOverflow) - assert.Equal(t, seq, 0) - return nil - }) - }) -} - -// Ensure that an error is returned when inserting into a bucket that doesn't exist. -func TestTransactionPutBucketNotFound(t *testing.T) { - withOpenDB(func(db *DB, path string) { - err := db.Put("widgets", []byte("foo"), []byte("bar")) - assert.Equal(t, err, ErrBucketNotFound) - }) -} - -// Ensure that an error is returned when inserting with an empty key. -func TestTransactionPutEmptyKey(t *testing.T) { - withOpenDB(func(db *DB, path string) { - db.CreateBucket("widgets") - err := db.Put("widgets", []byte(""), []byte("bar")) - assert.Equal(t, err, ErrKeyRequired) - err = db.Put("widgets", nil, []byte("bar")) - assert.Equal(t, err, ErrKeyRequired) - }) -} - -// Ensure that an error is returned when inserting with a key that's too large. -func TestTransactionPutKeyTooLarge(t *testing.T) { - withOpenDB(func(db *DB, path string) { - db.CreateBucket("widgets") - err := db.Put("widgets", make([]byte, 32769), []byte("bar")) - assert.Equal(t, err, ErrKeyTooLarge) - }) -} - -// Ensure that an error is returned when deleting from a bucket that doesn't exist. -func TestTransactionDeleteBucketNotFound(t *testing.T) { - withOpenDB(func(db *DB, path string) { - err := db.DeleteBucket("widgets") - assert.Equal(t, err, ErrBucketNotFound) - }) -} - -// Ensure that a bucket can write random keys and values across multiple txns. -func TestTransactionPutSingle(t *testing.T) { - index := 0 - f := func(items testdata) bool { - withOpenDB(func(db *DB, path string) { - m := make(map[string][]byte) - - db.CreateBucket("widgets") - for _, item := range items { - if err := db.Put("widgets", item.Key, item.Value); err != nil { - panic("put error: " + err.Error()) - } - m[string(item.Key)] = item.Value - - // Verify all key/values so far. - i := 0 - for k, v := range m { - value, err := db.Get("widgets", []byte(k)) - if err != nil { - panic("get error: " + err.Error()) - } - if !bytes.Equal(value, v) { - db.CopyFile("/tmp/bolt.put.single.db", 0666) - t.Fatalf("value mismatch [run %d] (%d of %d):\nkey: %x\ngot: %x\nexp: %x", index, i, len(m), []byte(k), value, v) - } - i++ - } - } - - fmt.Fprint(os.Stderr, ".") - }) - index++ - return true - } - if err := quick.Check(f, qconfig()); err != nil { - t.Error(err) - } - fmt.Fprint(os.Stderr, "\n") -} - -// Ensure that a transaction can insert multiple key/value pairs at once. -func TestTransactionPutMultiple(t *testing.T) { - f := func(items testdata) bool { - withOpenDB(func(db *DB, path string) { - // Bulk insert all values. - db.CreateBucket("widgets") - txn, _ := db.RWTransaction() - b := txn.Bucket("widgets") - for _, item := range items { - assert.NoError(t, b.Put(item.Key, item.Value)) - } - assert.NoError(t, txn.Commit()) - - // Verify all items exist. - txn, _ = db.Transaction() - for _, item := range items { - value := txn.Bucket("widgets").Get(item.Key) - if !assert.Equal(t, item.Value, value) { - db.CopyFile("/tmp/bolt.put.multiple.db", 0666) - t.FailNow() - } - } - txn.Rollback() - }) - fmt.Fprint(os.Stderr, ".") - return true - } - if err := quick.Check(f, qconfig()); err != nil { - t.Error(err) - } - fmt.Fprint(os.Stderr, "\n") -} - -// Ensure that a transaction can delete all key/value pairs and return to a single leaf page. -func TestTransactionDelete(t *testing.T) { - f := func(items testdata) bool { - withOpenDB(func(db *DB, path string) { - // Bulk insert all values. - db.CreateBucket("widgets") - txn, _ := db.RWTransaction() - b := txn.Bucket("widgets") - for _, item := range items { - assert.NoError(t, b.Put(item.Key, item.Value)) - } - assert.NoError(t, txn.Commit()) - - // Remove items one at a time and check consistency. - for i, item := range items { - assert.NoError(t, db.Delete("widgets", item.Key)) - - // Anything before our deletion index should be nil. - txn, _ := db.Transaction() - for j, exp := range items { - if j > i { - value := txn.Bucket("widgets").Get(exp.Key) - if !assert.Equal(t, exp.Value, value) { - t.FailNow() - } - } else { - value := txn.Bucket("widgets").Get(exp.Key) - if !assert.Nil(t, value) { - t.FailNow() - } - } - } - txn.Rollback() - } + txn.Close() }) fmt.Fprint(os.Stderr, ".") return true |