ipfs-cluster/monitor/metrics/window_test.go
Hector Sanjuan 7711ab8cfd
Replace underlying slice with ring.Ring in metrics window
License: MIT
Signed-off-by: Adrian Lanzafame <adrianlanzafame92@gmail.com>
2019-04-18 16:09:18 +10:00

329 lines
6.0 KiB
Go

package metrics
import (
"testing"
"time"
"github.com/ipfs/ipfs-cluster/api"
)
func makeMetric(value string) *api.Metric {
metr := &api.Metric{
Name: "test",
Peer: "peer1",
Value: value,
Valid: true,
}
metr.SetTTL(5 * time.Second)
return metr
}
func TestNewWindow(t *testing.T) {
w := NewWindow(10)
w.window.Next()
}
func BenchmarkWindow_Add(b *testing.B) {
b.Run("window size 10", func(b *testing.B) {
mw := NewWindow(10)
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Add(makeMetric("1"))
}
})
b.Run("window size 25", func(b *testing.B) {
mw := NewWindow(25)
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Add(makeMetric("1"))
}
})
b.Run("window size 1000", func(b *testing.B) {
mw := NewWindow(1000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Add(makeMetric("1"))
}
})
}
func TestWindow_Latest(t *testing.T) {
t.Run("no metrics error", func(t *testing.T) {
mw := NewWindow(4)
_, err := mw.Latest()
if err != ErrNoMetrics {
t.Error("expected ErrNoMetrics")
}
})
t.Run("single latest value", func(t *testing.T) {
mw := NewWindow(4)
mw.Add(makeMetric("1"))
metr, err := mw.Latest()
if err != nil {
t.Fatal(err)
}
if metr.Value != "1" {
t.Error("expected different value")
}
})
}
func BenchmarkWindow_Latest(b *testing.B) {
b.Run("window size 10", func(b *testing.B) {
mw := NewWindow(10)
for i := 0; i < 10; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Add(makeMetric("1"))
}
})
b.Run("window size 25", func(b *testing.B) {
mw := NewWindow(25)
for i := 0; i < 25; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Add(makeMetric("1"))
}
})
b.Run("window size 1000", func(b *testing.B) {
mw := NewWindow(1000)
for i := 0; i < 1000; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Add(makeMetric("1"))
}
})
}
func TestWindow_All(t *testing.T) {
t.Run("empty window", func(t *testing.T) {
mw := NewWindow(4)
if len(mw.All()) != 0 {
t.Error("expected 0 metrics")
}
})
t.Run("half capacity", func(t *testing.T) {
mw := NewWindow(4)
mw.Add(makeMetric("1"))
mw.Add(makeMetric("2"))
all := mw.All()
if len(all) != 2 {
t.Fatalf("should only be storing 2 metrics: got: %d", len(all))
}
if all[0].Value != "2" {
t.Error("newest metric should be first")
}
if all[1].Value != "1" {
t.Error("older metric should be second")
}
})
t.Run("full capacity", func(t *testing.T) {
mw := NewWindow(4)
mw.Add(makeMetric("1"))
mw.Add(makeMetric("2"))
mw.Add(makeMetric("3"))
mw.Add(makeMetric("4"))
all := mw.All()
if len(all) != 4 {
t.Fatalf("should only be storing 4 metrics: got: %d", len(all))
}
if all[len(all)-1].Value != "1" {
t.Error("oldest metric should be 1")
}
})
t.Run("over flow capacity", func(t *testing.T) {
mw := NewWindow(4)
mw.Add(makeMetric("1"))
mw.Add(makeMetric("2"))
mw.Add(makeMetric("3"))
mw.Add(makeMetric("4"))
mw.Add(makeMetric("5"))
all := mw.All()
if len(all) != 4 {
t.Fatalf("should only be storing 4 metrics: got: %d", len(all))
}
if all[len(all)-1].Value != "2" {
t.Error("oldest metric should be 2")
}
})
}
func TestWindow_AddParallel(t *testing.T) {
t.Parallel()
mw := NewWindow(10)
t.Run("parallel adder 1", func(t *testing.T) {
for i := 0; i < 100; i++ {
mw.Add(makeMetric("adder 1"))
}
})
t.Run("parallel adder 2", func(t *testing.T) {
for i := 0; i < 100; i++ {
mw.Add(makeMetric("adder 2"))
}
})
}
func BenchmarkWindow_All(b *testing.B) {
b.Run("window size 10", func(b *testing.B) {
mw := NewWindow(10)
for i := 0; i < 10; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.All()
}
})
b.Run("window size 25", func(b *testing.B) {
mw := NewWindow(25)
for i := 0; i < 25; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.All()
}
})
b.Run("window size 1000", func(b *testing.B) {
mw := NewWindow(1000)
for i := 0; i < 1000; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.All()
}
})
}
func TestWindow_Distribution(t *testing.T) {
var tests = []struct {
name string
heartbeats []int64
want []int64
}{
{
"even 1 sec distribution",
[]int64{1, 1, 1, 1},
[]int64{1, 1, 1, 1},
},
{
"increasing latency distribution",
[]int64{1, 1, 2, 2, 3, 3, 4},
[]int64{4, 3, 3, 2, 2, 1, 1},
},
{
"random latency distribution",
[]int64{4, 1, 3, 9, 7, 8, 11, 18},
[]int64{18, 11, 8, 7, 9, 3, 1, 4},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mw := NewWindow(len(tt.heartbeats) + 1)
for i, v := range tt.heartbeats {
mw.Add(makeMetric(string(v)))
time.Sleep(time.Duration(v) * time.Millisecond)
if i == len(tt.heartbeats)-1 {
mw.Add(makeMetric("last"))
}
}
got := mw.Distribution()
if len(got) != len(tt.want) {
t.Errorf("want len: %v, got len: %v", len(tt.want), len(got))
}
var gotseconds []int64
for _, v := range got {
// truncate nanoseconds to seconds for testing purposes
gotseconds = append(gotseconds, v/1000000)
}
for i, s := range gotseconds {
if s != tt.want[i] {
t.Fatalf("want: %v, got: %v", tt.want, gotseconds)
break
}
}
})
}
}
func BenchmarkWindow_Distribution(b *testing.B) {
b.Run("window size 10", func(b *testing.B) {
mw := NewWindow(10)
for i := 0; i < 10; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Distribution()
}
})
b.Run("window size 25", func(b *testing.B) {
mw := NewWindow(25)
for i := 0; i < 25; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Distribution()
}
})
b.Run("window size 1000", func(b *testing.B) {
mw := NewWindow(1000)
for i := 0; i < 1000; i++ {
mw.Add(makeMetric("1"))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
mw.Distribution()
}
})
}