Files
kopia/tests/stress_test/stress_test.go
Jarek Kowalski 72520029b0 golangci-lint: added more linters
Also fixed pre-existing lint errors.
2019-06-02 22:56:57 -07:00

131 lines
3.1 KiB
Go

package stress_test
import (
"context"
"fmt"
"math/rand"
"os"
"reflect"
"testing"
"time"
"github.com/kopia/kopia/internal/blobtesting"
"github.com/kopia/kopia/repo/blob"
"github.com/kopia/kopia/repo/content"
)
const goroutineCount = 16
func TestStressBlockManager(t *testing.T) {
if testing.Short() {
t.Skip("skipping stress test during short tests")
}
data := blobtesting.DataMap{}
keyTimes := map[blob.ID]time.Time{}
memst := blobtesting.NewMapStorage(data, keyTimes, time.Now)
var duration = 3 * time.Second
if os.Getenv("KOPIA_LONG_STRESS_TEST") != "" {
duration = 3 * time.Minute
}
stressTestWithStorage(t, memst, duration)
}
func stressTestWithStorage(t *testing.T, st blob.Storage, duration time.Duration) {
ctx := context.Background()
openMgr := func() (*content.Manager, error) {
return content.NewManager(ctx, st, &content.FormattingOptions{
Version: 1,
Hash: "HMAC-SHA256-128",
Encryption: "AES-256-CTR",
MaxPackSize: 20000000,
MasterKey: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
}, content.CachingOptions{}, nil)
}
seed0 := time.Now().Nanosecond()
t.Logf("running with seed %v", seed0)
deadline := time.Now().Add(duration)
t.Run("workers", func(t *testing.T) {
for i := 0; i < goroutineCount; i++ {
i := i
t.Run(fmt.Sprintf("worker-%v", i), func(t *testing.T) {
t.Parallel()
stressWorker(ctx, t, deadline, openMgr, int64(seed0+i))
})
}
})
}
func stressWorker(ctx context.Context, t *testing.T, deadline time.Time, openMgr func() (*content.Manager, error), seed int64) {
src := rand.NewSource(seed)
rnd := rand.New(src)
bm, err := openMgr()
if err != nil {
t.Fatalf("error opening manager: %v", err)
}
type writtenBlock struct {
contentID content.ID
data []byte
}
var workerBlocks []writtenBlock
for time.Now().Before(deadline) {
l := rnd.Intn(30000)
data := make([]byte, l)
if _, err := rnd.Read(data); err != nil {
t.Errorf("err: %v", err)
return
}
dataCopy := append([]byte{}, data...)
contentID, err := bm.WriteContent(ctx, data, "")
if err != nil {
t.Errorf("err: %v", err)
return
}
switch rnd.Intn(20) {
case 0:
if ferr := bm.Flush(ctx); ferr != nil {
t.Errorf("flush error: %v", ferr)
return
}
case 1:
if ferr := bm.Flush(ctx); ferr != nil {
t.Errorf("flush error: %v", ferr)
return
}
bm, err = openMgr()
if err != nil {
t.Errorf("error opening: %v", err)
return
}
}
workerBlocks = append(workerBlocks, writtenBlock{contentID, dataCopy})
if len(workerBlocks) > 5 {
pos := rnd.Intn(len(workerBlocks))
previous := workerBlocks[pos]
d2, err := bm.GetContent(ctx, previous.contentID)
if err != nil {
t.Errorf("error verifying content %q: %v", previous.contentID, err)
return
}
if !reflect.DeepEqual(previous.data, d2) {
t.Errorf("invalid previous data for %q %x %x", previous.contentID, d2, previous.data)
return
}
workerBlocks = append(workerBlocks[0:pos], workerBlocks[pos+1:]...)
}
}
}