blob: 1e6cdd163bb1240858500e159ef39268543205af [file] [edit]
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package buffer
import (
"testing"
)
func TestGrowthGrowing(t *testing.T) {
t.Parallel()
tests := map[string]struct {
ring *TypedRingGrowing[int]
initialSize int
}{
"implicit-zero": {
ring: new(TypedRingGrowing[int]),
},
"explicit-zero": {
ring: NewTypedRingGrowing[int](RingGrowingOptions{InitialSize: 0}),
initialSize: 0,
},
"nonzero": {
ring: NewTypedRingGrowing[int](RingGrowingOptions{InitialSize: 1}),
initialSize: 1,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
initialSize := test.initialSize
g := test.ring
if expected, actual := 0, g.Len(); expected != actual {
t.Fatalf("expected Len to be %d, got %d", expected, actual)
}
if expected, actual := initialSize, g.Cap(); expected != actual {
t.Fatalf("expected Cap to be %d, got %d", expected, actual)
}
x := 10
for i := 0; i < x; i++ {
if e, a := i, g.readable; e != a {
t.Fatalf("expected equal, got %#v, %#v", e, a)
}
g.WriteOne(i)
}
if expected, actual := x, g.Len(); expected != actual {
t.Fatalf("expected Len to be %d, got %d", expected, actual)
}
if expected, actual := 16, g.Cap(); expected != actual {
t.Fatalf("expected Cap to be %d, got %d", expected, actual)
}
read := 0
for g.readable > 0 {
v, ok := g.ReadOne()
if !ok {
t.Fatal("expected true")
}
if read != v {
t.Fatalf("expected %#v==%#v", read, v)
}
read++
}
if x != read {
t.Fatalf("expected to have read %d items: %d", x, read)
}
if expected, actual := 0, g.Len(); expected != actual {
t.Fatalf("expected Len to be %d, got %d", expected, actual)
}
if expected, actual := 16, g.Cap(); expected != actual {
t.Fatalf("expected Cap to be %d, got %d", expected, actual)
}
})
}
}
func TestGrowth(t *testing.T) {
t.Parallel()
tests := map[string]struct {
ring *Ring[int]
initialSize int
normalSize int
}{
"implicit-zero": {
ring: new(Ring[int]),
},
"explicit-zero": {
ring: NewRing[int](RingOptions{InitialSize: 0, NormalSize: 0}),
initialSize: 0,
normalSize: 0,
},
"smaller-initial-size": {
ring: NewRing[int](RingOptions{InitialSize: 1, NormalSize: 2}),
initialSize: 1,
normalSize: 2,
},
"smaller-normal-size": {
ring: NewRing[int](RingOptions{InitialSize: 2, NormalSize: 1}),
initialSize: 2,
normalSize: 1,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
initialSize := test.initialSize
normalSize := test.normalSize
g := test.ring
if expected, actual := 0, g.Len(); expected != actual {
t.Fatalf("expected Len to be %d, got %d", expected, actual)
}
if expected, actual := initialSize, g.Cap(); expected != actual {
t.Fatalf("expected Cap to be %d, got %d", expected, actual)
}
x := 10
for i := 0; i < x; i++ {
if e, a := i, g.growing.readable; e != a {
t.Fatalf("expected equal, got %#v, %#v", e, a)
}
g.WriteOne(i)
}
if expected, actual := x, g.Len(); expected != actual {
t.Fatalf("expected Len to be %d, got %d", expected, actual)
}
if expected, actual := 16, g.Cap(); expected != actual {
t.Fatalf("expected Cap to be %d, got %d", expected, actual)
}
read := 0
for g.growing.readable > 0 {
v, ok := g.ReadOne()
if !ok {
t.Fatal("expected true")
}
if read != v {
t.Fatalf("expected %#v==%#v", read, v)
}
read++
}
if x != read {
t.Fatalf("expected to have read %d items: %d", x, read)
}
if expected, actual := 0, g.Len(); expected != actual {
t.Fatalf("expected Len to be %d, got %d", expected, actual)
}
if expected, actual := normalSize, g.Cap(); expected != actual {
t.Fatalf("expected Cap to be %d, got %d", expected, actual)
}
})
}
}
func TestEmpty(t *testing.T) {
t.Parallel()
g := NewTypedRingGrowing[struct{}](RingGrowingOptions{InitialSize: 1})
_, ok := g.ReadOne()
if ok != false {
t.Fatal("expected false")
}
}
const (
spikeSize = 100 // Number of items to write during a spike
normalSize = 64 // Normal capacity for the Ring type after shrinking
initialSize = 16 // Initial capacity for buffers
)
func BenchmarkTypedRingGrowing_Spike(b *testing.B) {
b.ReportAllocs()
var item int // ensure item is used
for i := 0; i < b.N; i++ {
buffer := NewTypedRingGrowing[int](RingGrowingOptions{InitialSize: initialSize})
for j := 0; j < spikeSize; j++ {
buffer.WriteOne(j)
}
for buffer.Len() > 0 {
item, _ = buffer.ReadOne()
}
}
_ = item // use item
}
func BenchmarkRing_Spike_And_Shrink(b *testing.B) {
b.ReportAllocs()
var item int // ensure item is used
for i := 0; i < b.N; i++ {
// Create a new buffer for each benchmark iteration
buffer := NewRing[int](RingOptions{
InitialSize: initialSize,
NormalSize: normalSize,
})
for j := 0; j < spikeSize; j++ {
buffer.WriteOne(j)
}
for buffer.Len() > 0 {
item, _ = buffer.ReadOne()
}
}
_ = item // use item
}