Files
go-astikit/stat_test.go
2025-02-13 11:37:23 +01:00

88 lines
2.0 KiB
Go

package astikit
import (
"context"
"reflect"
"sync"
"sync/atomic"
"testing"
"time"
)
func TestStater(t *testing.T) {
// Update the now function so that it increments by 5s every time stats are computed
var c int64
mc := &sync.Mutex{} // Locks c
nowPrevious := now
defer func() { now = nowPrevious }()
mn := &sync.Mutex{} // Locks nowV
nowV := time.Unix(c*5, 0)
now = func() time.Time {
mn.Lock()
defer mn.Unlock()
return nowV
}
// Add stats
var u1 uint64
v1 := NewAtomicUint64RateStat(&u1)
m1 := &StatMetadata{Description: "1"}
o1 := StatOptions{Metadata: m1, Valuer: v1}
d2 := NewAtomicDuration(0)
v2 := NewAtomicDurationPercentageStat(d2)
m2 := &StatMetadata{Description: "2"}
o2 := StatOptions{Metadata: m2, Valuer: v2}
d3 := NewAtomicDuration(0)
v3 := NewAtomicDurationAvgStat(d3, &u1)
m3 := &StatMetadata{Description: "3"}
o3 := StatOptions{Metadata: m3, Valuer: v3}
v4 := StatValuerFunc(func(d time.Duration) any { return 42 })
m4 := &StatMetadata{Description: "4"}
o4 := StatOptions{Metadata: m4, Valuer: v4}
// First time stats are computed, it actually acts as if stats were being updated
// Second time stats are computed, results are stored and context is cancelled
var ss []StatValue
ctx, cancel := context.WithCancel(context.Background())
s := NewStater(StaterOptions{
HandleFunc: func(stats []StatValue) {
mc.Lock()
defer mc.Unlock()
c++
switch c {
case 1:
atomic.AddUint64(&u1, 10)
d2.Add(4 * time.Second)
d3.Add(10 * time.Second)
mn.Lock()
nowV = time.Unix(5, 0)
mn.Unlock()
case 2:
ss = stats
cancel()
}
},
Period: time.Millisecond,
})
s.AddStats(o1, o2, o3, o4)
s.Start(ctx)
defer s.Stop()
for _, e := range []StatValue{
{StatMetadata: m1, Value: 2.0},
{StatMetadata: m2, Value: 80.0},
{StatMetadata: m3, Value: time.Second},
{StatMetadata: m4, Value: 42},
} {
found := false
for _, s := range ss {
if reflect.DeepEqual(s, e) {
found = true
break
}
}
if !found {
t.Fatalf("expected %+v, not found", e)
}
}
}