test: get all concurrent test parameters wrapped in a struct

Signed-off-by: Benjamin Wang <wachao@vmware.com>
This commit is contained in:
Benjamin Wang 2023-04-14 19:02:28 +08:00
parent 96372dea01
commit 8ca298f17f

View File

@ -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))
} }
} }