mirror of
https://github.com/etcd-io/bbolt.git
synced 2025-05-31 11:42:30 +00:00
test: get all concurrent test parameters wrapped in a struct
Signed-off-by: Benjamin Wang <wachao@vmware.com>
This commit is contained in:
parent
96372dea01
commit
8ca298f17f
@ -24,6 +24,22 @@ import (
|
|||||||
"go.etcd.io/bbolt/internal/common"
|
"go.etcd.io/bbolt/internal/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type duration struct {
|
||||||
|
min time.Duration
|
||||||
|
max time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type bytesRange struct {
|
||||||
|
min int
|
||||||
|
max int
|
||||||
|
}
|
||||||
|
|
||||||
|
type concurrentConfig struct {
|
||||||
|
readTime duration
|
||||||
|
writeTime duration
|
||||||
|
writeBytes bytesRange
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TestConcurrentReadAndWrite verifies:
|
TestConcurrentReadAndWrite verifies:
|
||||||
1. Repeatable read: a read transaction should always see the same data
|
1. Repeatable read: a read transaction should always see the same data
|
||||||
@ -36,59 +52,88 @@ func TestConcurrentReadAndWrite(t *testing.T) {
|
|||||||
keys := []string{"key0", "key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8", "key9"}
|
keys := []string{"key0", "key1", "key2", "key3", "key4", "key5", "key6", "key7", "key8", "key9"}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
readerCount int
|
readerCount int
|
||||||
minReadInterval time.Duration
|
conf concurrentConfig
|
||||||
maxReadInterval time.Duration
|
testDuration time.Duration
|
||||||
minWriteInterval time.Duration
|
|
||||||
maxWriteInterval time.Duration
|
|
||||||
minWriteBytes int
|
|
||||||
maxWriteBytes int
|
|
||||||
testDuration time.Duration
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "1 reader",
|
name: "1 reader",
|
||||||
readerCount: 1,
|
readerCount: 1,
|
||||||
minReadInterval: 50 * time.Millisecond,
|
conf: concurrentConfig{
|
||||||
maxReadInterval: 100 * time.Millisecond,
|
readTime: duration{
|
||||||
minWriteInterval: 10 * time.Millisecond,
|
min: 50 * time.Millisecond,
|
||||||
maxWriteInterval: 20 * time.Millisecond,
|
max: 100 * time.Millisecond,
|
||||||
minWriteBytes: 200,
|
},
|
||||||
maxWriteBytes: 8000,
|
writeTime: duration{
|
||||||
testDuration: 30 * time.Second,
|
min: 10 * time.Millisecond,
|
||||||
|
max: 20 * time.Millisecond,
|
||||||
|
},
|
||||||
|
writeBytes: bytesRange{
|
||||||
|
min: 200,
|
||||||
|
max: 8000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testDuration: 30 * time.Second,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "10 readers",
|
name: "10 readers",
|
||||||
readerCount: 10,
|
readerCount: 10,
|
||||||
minReadInterval: 50 * time.Millisecond,
|
conf: concurrentConfig{
|
||||||
maxReadInterval: 100 * time.Millisecond,
|
readTime: duration{
|
||||||
minWriteInterval: 10 * time.Millisecond,
|
min: 50 * time.Millisecond,
|
||||||
maxWriteInterval: 20 * time.Millisecond,
|
max: 100 * time.Millisecond,
|
||||||
minWriteBytes: 200,
|
},
|
||||||
maxWriteBytes: 8000,
|
writeTime: duration{
|
||||||
testDuration: 30 * time.Second,
|
min: 10 * time.Millisecond,
|
||||||
|
max: 20 * time.Millisecond,
|
||||||
|
},
|
||||||
|
writeBytes: bytesRange{
|
||||||
|
min: 200,
|
||||||
|
max: 8000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
testDuration: 30 * time.Second,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "50 readers",
|
name: "50 readers",
|
||||||
readerCount: 50,
|
readerCount: 50,
|
||||||
minReadInterval: 50 * time.Millisecond,
|
conf: concurrentConfig{
|
||||||
maxReadInterval: 100 * time.Millisecond,
|
readTime: duration{
|
||||||
minWriteInterval: 10 * time.Millisecond,
|
min: 50 * time.Millisecond,
|
||||||
maxWriteInterval: 20 * time.Millisecond,
|
max: 100 * time.Millisecond,
|
||||||
minWriteBytes: 500,
|
},
|
||||||
maxWriteBytes: 8000,
|
writeTime: duration{
|
||||||
testDuration: 30 * time.Second,
|
min: 10 * time.Millisecond,
|
||||||
|
max: 20 * time.Millisecond,
|
||||||
|
},
|
||||||
|
writeBytes: bytesRange{
|
||||||
|
min: 500,
|
||||||
|
max: 8000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
testDuration: 30 * time.Second,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "100 readers",
|
name: "100 readers",
|
||||||
readerCount: 100,
|
readerCount: 100,
|
||||||
minReadInterval: 50 * time.Millisecond,
|
conf: concurrentConfig{
|
||||||
maxReadInterval: 100 * time.Millisecond,
|
readTime: duration{
|
||||||
minWriteInterval: 10 * time.Millisecond,
|
min: 50 * time.Millisecond,
|
||||||
maxWriteInterval: 20 * time.Millisecond,
|
max: 100 * time.Millisecond,
|
||||||
minWriteBytes: 500,
|
},
|
||||||
maxWriteBytes: 8000,
|
writeTime: duration{
|
||||||
testDuration: 30 * time.Second,
|
min: 10 * time.Millisecond,
|
||||||
|
max: 20 * time.Millisecond,
|
||||||
|
},
|
||||||
|
writeBytes: bytesRange{
|
||||||
|
min: 500,
|
||||||
|
max: 8000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
testDuration: 30 * time.Second,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +144,7 @@ func TestConcurrentReadAndWrite(t *testing.T) {
|
|||||||
bucket,
|
bucket,
|
||||||
keys,
|
keys,
|
||||||
tc.readerCount,
|
tc.readerCount,
|
||||||
tc.minReadInterval, tc.maxReadInterval,
|
tc.conf,
|
||||||
tc.minWriteInterval, tc.maxWriteInterval,
|
|
||||||
tc.minWriteBytes, tc.maxWriteBytes,
|
|
||||||
tc.testDuration)
|
tc.testDuration)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -111,9 +154,7 @@ func concurrentReadAndWrite(t *testing.T,
|
|||||||
bucket []byte,
|
bucket []byte,
|
||||||
keys []string,
|
keys []string,
|
||||||
readerCount int,
|
readerCount int,
|
||||||
minReadInterval, maxReadInterval time.Duration,
|
conf concurrentConfig,
|
||||||
minWriteInterval, maxWriteInterval time.Duration,
|
|
||||||
minWriteBytes, maxWriteBytes int,
|
|
||||||
testDuration time.Duration) {
|
testDuration time.Duration) {
|
||||||
|
|
||||||
t.Log("Preparing db.")
|
t.Log("Preparing db.")
|
||||||
@ -127,8 +168,8 @@ func concurrentReadAndWrite(t *testing.T,
|
|||||||
t.Log("Starting workers.")
|
t.Log("Starting workers.")
|
||||||
records := runWorkers(t,
|
records := runWorkers(t,
|
||||||
db, bucket, keys,
|
db, bucket, keys,
|
||||||
readerCount, minReadInterval, maxReadInterval,
|
readerCount,
|
||||||
minWriteInterval, maxWriteInterval, minWriteBytes, maxWriteBytes,
|
conf,
|
||||||
testDuration)
|
testDuration)
|
||||||
|
|
||||||
t.Log("Analyzing the history records.")
|
t.Log("Analyzing the history records.")
|
||||||
@ -154,9 +195,7 @@ func runWorkers(t *testing.T,
|
|||||||
bucket []byte,
|
bucket []byte,
|
||||||
keys []string,
|
keys []string,
|
||||||
readerCount int,
|
readerCount int,
|
||||||
minReadInterval, maxReadInterval time.Duration,
|
conf concurrentConfig,
|
||||||
minWriteInterval, maxWriteInterval time.Duration,
|
|
||||||
minWriteBytes, maxWriteBytes int,
|
|
||||||
testDuration time.Duration) historyRecords {
|
testDuration time.Duration) historyRecords {
|
||||||
stopCh := make(chan struct{}, 1)
|
stopCh := make(chan struct{}, 1)
|
||||||
errCh := make(chan error, readerCount+1)
|
errCh := make(chan error, readerCount+1)
|
||||||
@ -167,13 +206,12 @@ func runWorkers(t *testing.T,
|
|||||||
// start write transaction
|
// start write transaction
|
||||||
g := new(errgroup.Group)
|
g := new(errgroup.Group)
|
||||||
writer := writeWorker{
|
writer := writeWorker{
|
||||||
db: db,
|
db: db,
|
||||||
bucket: bucket,
|
bucket: bucket,
|
||||||
keys: keys,
|
keys: keys,
|
||||||
minWriteBytes: minWriteBytes,
|
|
||||||
maxWriteBytes: maxWriteBytes,
|
writeBytes: conf.writeBytes,
|
||||||
minWriteInterval: minWriteInterval,
|
writeTime: conf.writeTime,
|
||||||
maxWriteInterval: maxWriteInterval,
|
|
||||||
|
|
||||||
errCh: errCh,
|
errCh: errCh,
|
||||||
stopCh: stopCh,
|
stopCh: stopCh,
|
||||||
@ -190,11 +228,11 @@ func runWorkers(t *testing.T,
|
|||||||
// start readonly transactions
|
// start readonly transactions
|
||||||
for i := 0; i < readerCount; i++ {
|
for i := 0; i < readerCount; i++ {
|
||||||
reader := &readWorker{
|
reader := &readWorker{
|
||||||
db: db,
|
db: db,
|
||||||
bucket: bucket,
|
bucket: bucket,
|
||||||
keys: keys,
|
keys: keys,
|
||||||
minReadInterval: minReadInterval,
|
|
||||||
maxReadInterval: maxReadInterval,
|
readTime: conf.readTime,
|
||||||
|
|
||||||
errCh: errCh,
|
errCh: errCh,
|
||||||
stopCh: stopCh,
|
stopCh: stopCh,
|
||||||
@ -230,8 +268,7 @@ type readWorker struct {
|
|||||||
bucket []byte
|
bucket []byte
|
||||||
keys []string
|
keys []string
|
||||||
|
|
||||||
minReadInterval time.Duration
|
readTime duration
|
||||||
maxReadInterval time.Duration
|
|
||||||
|
|
||||||
errCh chan error
|
errCh chan error
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
@ -254,7 +291,7 @@ func (r *readWorker) run() (historyRecords, error) {
|
|||||||
|
|
||||||
selectedKey := r.keys[mrand.Intn(len(r.keys))]
|
selectedKey := r.keys[mrand.Intn(len(r.keys))]
|
||||||
initialVal := b.Get([]byte(selectedKey))
|
initialVal := b.Get([]byte(selectedKey))
|
||||||
time.Sleep(randomDurationInRange(r.minReadInterval, r.maxReadInterval))
|
time.Sleep(randomDurationInRange(r.readTime.min, r.readTime.max))
|
||||||
val := b.Get([]byte(selectedKey))
|
val := b.Get([]byte(selectedKey))
|
||||||
|
|
||||||
if !reflect.DeepEqual(initialVal, val) {
|
if !reflect.DeepEqual(initialVal, val) {
|
||||||
@ -290,10 +327,8 @@ type writeWorker struct {
|
|||||||
bucket []byte
|
bucket []byte
|
||||||
keys []string
|
keys []string
|
||||||
|
|
||||||
minWriteBytes int
|
writeBytes bytesRange
|
||||||
maxWriteBytes int
|
writeTime duration
|
||||||
minWriteInterval time.Duration
|
|
||||||
maxWriteInterval time.Duration
|
|
||||||
|
|
||||||
errCh chan error
|
errCh chan error
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
@ -316,7 +351,7 @@ func (w *writeWorker) run() (historyRecords, error) {
|
|||||||
|
|
||||||
selectedKey := w.keys[mrand.Intn(len(w.keys))]
|
selectedKey := w.keys[mrand.Intn(len(w.keys))]
|
||||||
|
|
||||||
valueBytes := randomIntInRange(w.minWriteBytes, w.maxWriteBytes)
|
valueBytes := randomIntInRange(w.writeBytes.min, w.writeBytes.max)
|
||||||
v := make([]byte, valueBytes)
|
v := make([]byte, valueBytes)
|
||||||
if _, cErr := crand.Read(v); cErr != nil {
|
if _, cErr := crand.Read(v); cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
@ -342,7 +377,7 @@ func (w *writeWorker) run() (historyRecords, error) {
|
|||||||
return rs, writeErr
|
return rs, writeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(randomDurationInRange(w.minWriteInterval, w.maxWriteInterval))
|
time.Sleep(randomDurationInRange(w.writeTime.min, w.writeTime.max))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user