mirror of https://github.com/etcd-io/bbolt.git
commit
53828385e0
2
node.go
2
node.go
|
@ -40,7 +40,7 @@ func (n *node) root() *node {
|
||||||
if n.parent == nil {
|
if n.parent == nil {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
return n.parent
|
return n.parent.root()
|
||||||
}
|
}
|
||||||
|
|
||||||
// put inserts a key/value.
|
// put inserts a key/value.
|
||||||
|
|
|
@ -1,30 +1,27 @@
|
||||||
package bolt
|
package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testing/quick defaults to 100 iterations and a random seed.
|
// testing/quick defaults to 5 iterations and a random seed.
|
||||||
// You can override these settings from the command line:
|
// You can override these settings from the command line:
|
||||||
//
|
//
|
||||||
// -quickchecks The number of iterations to perform.
|
// -quick.count The number of iterations to perform.
|
||||||
// -quick.seed The seed to use for randomizing.
|
// -quick.seed The seed to use for randomizing.
|
||||||
// -quick.maxitems The maximum number of items to insert into a DB.
|
// -quick.maxitems The maximum number of items to insert into a DB.
|
||||||
// -quick.maxksize The maximum size of a key.
|
// -quick.maxksize The maximum size of a key.
|
||||||
// -quick.maxvsize The maximum size of a value.
|
// -quick.maxvsize The maximum size of a value.
|
||||||
//
|
//
|
||||||
|
|
||||||
var qseed, qmaxitems, qmaxksize, qmaxvsize int
|
var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
flag.IntVar(&qcount, "quick.count", 5, "")
|
||||||
flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "")
|
flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "")
|
||||||
flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "")
|
flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "")
|
||||||
flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "")
|
flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "")
|
||||||
|
@ -33,45 +30,11 @@ func init() {
|
||||||
warn("seed:", qseed)
|
warn("seed:", qseed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that a bucket can write random keys and values across multiple txns.
|
func qconfig() *quick.Config {
|
||||||
func TestQuickPut(t *testing.T) {
|
return &quick.Config{
|
||||||
index := 0
|
MaxCount: qcount,
|
||||||
f := func(items testdata) bool {
|
Rand: rand.New(rand.NewSource(int64(qseed))),
|
||||||
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.random.db")
|
|
||||||
t.Fatalf("value mismatch [run %d] (%d of %d):\nkey: %x\ngot: %x\nexp: %x", index, i, len(m), []byte(k), v, value)
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprint(os.Stderr, ".")
|
|
||||||
})
|
|
||||||
index++
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if err := quick.Check(f, &quick.Config{Rand: rand.New(rand.NewSource(int64(qseed)))}); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
fmt.Fprint(os.Stderr, "\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type testdata []testdataitem
|
type testdata []testdataitem
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
package bolt
|
package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"testing/quick"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ensure that a RWTransaction can be retrieved.
|
// Ensure that a RWTransaction can be retrieved.
|
||||||
func TestRWTransaction(t *testing.T) {
|
func TestRWTransaction(t *testing.T) {
|
||||||
withOpenDB(func(db *DB, path string) {
|
withOpenDB(func(db *DB, path string) {
|
||||||
|
@ -61,3 +64,74 @@ func TestTransactionCreateBucketWithLongName(t *testing.T) {
|
||||||
assert.Equal(t, err, &Error{"bucket name too long", nil})
|
assert.Equal(t, err, &Error{"bucket name too long", nil})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that a bucket can write random keys and values across multiple txns.
|
||||||
|
func TestRWTransactionPutSingle(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")
|
||||||
|
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 TestRWTransactionPutMultiple(t *testing.T) {
|
||||||
|
f := func(items testdata) bool {
|
||||||
|
withOpenDB(func(db *DB, path string) {
|
||||||
|
// Bulk insert all values.
|
||||||
|
db.CreateBucket("widgets")
|
||||||
|
rwtxn, _ := db.RWTransaction()
|
||||||
|
for _, item := range items {
|
||||||
|
assert.NoError(t, rwtxn.Put("widgets", item.Key, item.Value))
|
||||||
|
}
|
||||||
|
assert.NoError(t, rwtxn.Commit())
|
||||||
|
|
||||||
|
// Verify all items exist.
|
||||||
|
txn, _ := db.Transaction()
|
||||||
|
for _, item := range items {
|
||||||
|
if !assert.Equal(t, item.Value, txn.Get("widgets", item.Key)) {
|
||||||
|
db.CopyFile("/tmp/bolt.put.multiple.db")
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
txn.Close()
|
||||||
|
})
|
||||||
|
fmt.Fprint(os.Stderr, ".")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if err := quick.Check(f, qconfig()); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Fprint(os.Stderr, "\n")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue