mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-18 19:15:19 +00:00
6755a9ca63
* Fix bufferpool puts (ref #4976) There was a logic error in Put() which made us put all large blocks into segment zero, where we subsequently did not look for them. I also added a lowest threshold, as we otherwise allocate a 128KiB buffer when we need 24 bytes for a header and such. * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * smaller stress * cap/len * wip * wip
133 lines
2.6 KiB
Go
133 lines
2.6 KiB
Go
// Copyright (C) 2019 The Protocol Authors.
|
|
|
|
package protocol
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/syncthing/syncthing/lib/rand"
|
|
)
|
|
|
|
func TestGetBucketNumbers(t *testing.T) {
|
|
cases := []struct {
|
|
size int
|
|
bkt int
|
|
panics bool
|
|
}{
|
|
{size: 1024, bkt: 0},
|
|
{size: MinBlockSize, bkt: 0},
|
|
{size: MinBlockSize + 1, bkt: 1},
|
|
{size: 2*MinBlockSize - 1, bkt: 1},
|
|
{size: 2 * MinBlockSize, bkt: 1},
|
|
{size: 2*MinBlockSize + 1, bkt: 2},
|
|
{size: MaxBlockSize, bkt: len(BlockSizes) - 1},
|
|
{size: MaxBlockSize + 1, panics: true},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
if tc.panics {
|
|
shouldPanic(t, func() { getBucketForLen(tc.size) })
|
|
} else {
|
|
res := getBucketForLen(tc.size)
|
|
if res != tc.bkt {
|
|
t.Errorf("block of size %d should get from bucket %d, not %d", tc.size, tc.bkt, res)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPutBucketNumbers(t *testing.T) {
|
|
cases := []struct {
|
|
size int
|
|
bkt int
|
|
panics bool
|
|
}{
|
|
{size: 1024, panics: true},
|
|
{size: MinBlockSize, bkt: 0},
|
|
{size: MinBlockSize + 1, panics: true},
|
|
{size: 2 * MinBlockSize, bkt: 1},
|
|
{size: MaxBlockSize, bkt: len(BlockSizes) - 1},
|
|
{size: MaxBlockSize + 1, panics: true},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
if tc.panics {
|
|
shouldPanic(t, func() { putBucketForCap(tc.size) })
|
|
} else {
|
|
res := putBucketForCap(tc.size)
|
|
if res != tc.bkt {
|
|
t.Errorf("block of size %d should put into bucket %d, not %d", tc.size, tc.bkt, res)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStressBufferPool(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip()
|
|
}
|
|
|
|
const routines = 10
|
|
const runtime = 2 * time.Second
|
|
|
|
bp := newBufferPool()
|
|
t0 := time.Now()
|
|
|
|
var wg sync.WaitGroup
|
|
fail := make(chan struct{}, routines)
|
|
for i := 0; i < routines; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
for time.Since(t0) < runtime {
|
|
blocks := make([][]byte, 10)
|
|
for i := range blocks {
|
|
// Request a block of random size with the range
|
|
// covering smaller-than-min to larger-than-max and
|
|
// everything in between.
|
|
want := rand.Intn(1.5 * MaxBlockSize)
|
|
blocks[i] = bp.Get(want)
|
|
if len(blocks[i]) != want {
|
|
fail <- struct{}{}
|
|
return
|
|
}
|
|
}
|
|
for i := range blocks {
|
|
bp.Put(blocks[i])
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
select {
|
|
case <-fail:
|
|
t.Fatal("a block was bad size")
|
|
default:
|
|
}
|
|
|
|
t.Log(bp.puts, bp.skips, bp.misses, bp.hits)
|
|
if bp.puts == 0 || bp.skips == 0 || bp.misses == 0 {
|
|
t.Error("didn't exercise some paths")
|
|
}
|
|
var hits int64
|
|
for _, h := range bp.hits {
|
|
hits += h
|
|
}
|
|
if hits == 0 {
|
|
t.Error("didn't exercise some paths")
|
|
}
|
|
}
|
|
|
|
func shouldPanic(t *testing.T, fn func()) {
|
|
defer func() {
|
|
if r := recover(); r == nil {
|
|
t.Errorf("did not panic")
|
|
}
|
|
}()
|
|
|
|
fn()
|
|
}
|