mirror of
https://github.com/luxfi/math.git
synced 2026-07-27 03:38:49 +00:00
167 lines
3.2 KiB
Go
167 lines
3.2 KiB
Go
// Copyright (C) 2019-2024, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package meter
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var (
|
|
halflife = time.Second
|
|
meters = []struct {
|
|
name string
|
|
factory Factory
|
|
}{
|
|
{
|
|
name: "continuous",
|
|
factory: ContinuousFactory{},
|
|
},
|
|
}
|
|
|
|
meterTests = []struct {
|
|
name string
|
|
test func(*testing.T, Factory)
|
|
}{
|
|
{
|
|
name: "new",
|
|
test: NewTest,
|
|
},
|
|
{
|
|
name: "standard usage",
|
|
test: StandardUsageTest,
|
|
},
|
|
{
|
|
name: "time travel",
|
|
test: TimeTravelTest,
|
|
},
|
|
}
|
|
)
|
|
|
|
func TestMeters(t *testing.T) {
|
|
for _, s := range meters {
|
|
for _, test := range meterTests {
|
|
t.Run(fmt.Sprintf("meter %s test %s", s.name, test.name), func(t *testing.T) {
|
|
test.test(t, s.factory)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func NewTest(t *testing.T, factory Factory) {
|
|
require.NotNil(t, factory.New(halflife))
|
|
}
|
|
|
|
func TimeTravelTest(t *testing.T, factory Factory) {
|
|
require := require.New(t)
|
|
|
|
m := factory.New(halflife)
|
|
|
|
now := time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC)
|
|
m.Inc(now, 1)
|
|
|
|
now = now.Add(halflife - 1)
|
|
delta := 0.0001
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
|
|
m.Dec(now, 1)
|
|
|
|
now = now.Add(-halflife)
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
|
|
m.Inc(now, 1)
|
|
|
|
now = now.Add(halflife / 2)
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
}
|
|
|
|
func StandardUsageTest(t *testing.T, factory Factory) {
|
|
require := require.New(t)
|
|
|
|
m := factory.New(halflife)
|
|
|
|
now := time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC)
|
|
m.Inc(now, 1)
|
|
|
|
now = now.Add(halflife - 1)
|
|
delta := 0.0001
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
|
|
m.Inc(now, 1)
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
|
|
m.Dec(now, 1)
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
|
|
m.Dec(now, 1)
|
|
|
|
require.InDelta(.5, m.Read(now), delta)
|
|
|
|
now = now.Add(halflife)
|
|
require.InDelta(.25, m.Read(now), delta)
|
|
|
|
m.Inc(now, 1)
|
|
|
|
now = now.Add(halflife)
|
|
require.InDelta(.625, m.Read(now), delta)
|
|
|
|
now = now.Add(34 * halflife)
|
|
require.InDelta(1, m.Read(now), delta)
|
|
|
|
m.Dec(now, 1)
|
|
|
|
now = now.Add(34 * halflife)
|
|
require.InDelta(0, m.Read(now), delta)
|
|
|
|
m.Inc(now, 1)
|
|
|
|
now = now.Add(2 * halflife)
|
|
require.InDelta(.75, m.Read(now), delta)
|
|
|
|
// Second start
|
|
m.Inc(now, 1)
|
|
|
|
now = now.Add(34 * halflife)
|
|
require.InDelta(2, m.Read(now), delta)
|
|
|
|
// Stop the second CPU
|
|
m.Dec(now, 1)
|
|
|
|
now = now.Add(34 * halflife)
|
|
require.InDelta(1, m.Read(now), delta)
|
|
}
|
|
|
|
func TestTimeUntil(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
halflife := 5 * time.Second
|
|
f := ContinuousFactory{}
|
|
m := f.New(halflife)
|
|
now := time.Now()
|
|
// Start the meter
|
|
m.Inc(now, 1)
|
|
// One halflife passes; stop the meter
|
|
now = now.Add(halflife)
|
|
m.Dec(now, 1)
|
|
// Read the current value
|
|
currentVal := m.Read(now)
|
|
// Suppose we want to wait for the value to be
|
|
// a third of its current value
|
|
desiredVal := currentVal / 3
|
|
// See when that should happen
|
|
timeUntilDesiredVal := m.TimeUntil(now, desiredVal)
|
|
// Get the actual value at that time
|
|
now = now.Add(timeUntilDesiredVal)
|
|
actualVal := m.Read(now)
|
|
// Make sure the actual/expected are close
|
|
require.InDelta(desiredVal, actualVal, .00001)
|
|
// Make sure TimeUntil returns the zero duration if
|
|
// the value provided >= the current value
|
|
require.Zero(m.TimeUntil(now, actualVal))
|
|
require.Zero(m.TimeUntil(now, actualVal+.1))
|
|
}
|