github.com/MetalBlockchain/metalgo@v1.11.9/utils/math/meter/meter_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package meter 5 6 import ( 7 "fmt" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/require" 12 ) 13 14 var ( 15 halflife = time.Second 16 meters = []struct { 17 name string 18 factory Factory 19 }{ 20 { 21 name: "continuous", 22 factory: ContinuousFactory{}, 23 }, 24 } 25 26 meterTests = []struct { 27 name string 28 test func(*testing.T, Factory) 29 }{ 30 { 31 name: "new", 32 test: NewTest, 33 }, 34 { 35 name: "standard usage", 36 test: StandardUsageTest, 37 }, 38 { 39 name: "time travel", 40 test: TimeTravelTest, 41 }, 42 } 43 ) 44 45 func TestMeters(t *testing.T) { 46 for _, s := range meters { 47 for _, test := range meterTests { 48 t.Run(fmt.Sprintf("meter %s test %s", s.name, test.name), func(t *testing.T) { 49 test.test(t, s.factory) 50 }) 51 } 52 } 53 } 54 55 func NewTest(t *testing.T, factory Factory) { 56 require.NotNil(t, factory.New(halflife)) 57 } 58 59 func TimeTravelTest(t *testing.T, factory Factory) { 60 require := require.New(t) 61 62 m := factory.New(halflife) 63 64 now := time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC) 65 m.Inc(now, 1) 66 67 now = now.Add(halflife - 1) 68 delta := 0.0001 69 require.InDelta(.5, m.Read(now), delta) 70 71 m.Dec(now, 1) 72 73 now = now.Add(-halflife) 74 require.InDelta(.5, m.Read(now), delta) 75 76 m.Inc(now, 1) 77 78 now = now.Add(halflife / 2) 79 require.InDelta(.5, m.Read(now), delta) 80 } 81 82 func StandardUsageTest(t *testing.T, factory Factory) { 83 require := require.New(t) 84 85 m := factory.New(halflife) 86 87 now := time.Date(1, 2, 3, 4, 5, 6, 7, time.UTC) 88 m.Inc(now, 1) 89 90 now = now.Add(halflife - 1) 91 delta := 0.0001 92 require.InDelta(.5, m.Read(now), delta) 93 94 m.Inc(now, 1) 95 require.InDelta(.5, m.Read(now), delta) 96 97 m.Dec(now, 1) 98 require.InDelta(.5, m.Read(now), delta) 99 100 m.Dec(now, 1) 101 102 require.InDelta(.5, m.Read(now), delta) 103 104 now = now.Add(halflife) 105 require.InDelta(.25, m.Read(now), delta) 106 107 m.Inc(now, 1) 108 109 now = now.Add(halflife) 110 require.InDelta(.625, m.Read(now), delta) 111 112 now = now.Add(34 * halflife) 113 require.InDelta(1, m.Read(now), delta) 114 115 m.Dec(now, 1) 116 117 now = now.Add(34 * halflife) 118 require.InDelta(0, m.Read(now), delta) 119 120 m.Inc(now, 1) 121 122 now = now.Add(2 * halflife) 123 require.InDelta(.75, m.Read(now), delta) 124 125 // Second start 126 m.Inc(now, 1) 127 128 now = now.Add(34 * halflife) 129 require.InDelta(2, m.Read(now), delta) 130 131 // Stop the second CPU 132 m.Dec(now, 1) 133 134 now = now.Add(34 * halflife) 135 require.InDelta(1, m.Read(now), delta) 136 } 137 138 func TestTimeUntil(t *testing.T) { 139 require := require.New(t) 140 141 halflife := 5 * time.Second 142 f := ContinuousFactory{} 143 m := f.New(halflife) 144 now := time.Now() 145 // Start the meter 146 m.Inc(now, 1) 147 // One halflife passes; stop the meter 148 now = now.Add(halflife) 149 m.Dec(now, 1) 150 // Read the current value 151 currentVal := m.Read(now) 152 // Suppose we want to wait for the value to be 153 // a third of its current value 154 desiredVal := currentVal / 3 155 // See when that should happen 156 timeUntilDesiredVal := m.TimeUntil(now, desiredVal) 157 // Get the actual value at that time 158 now = now.Add(timeUntilDesiredVal) 159 actualVal := m.Read(now) 160 // Make sure the actual/expected are close 161 require.InDelta(desiredVal, actualVal, .00001) 162 // Make sure TimeUntil returns the zero duration if 163 // the value provided >= the current value 164 require.Zero(m.TimeUntil(now, actualVal)) 165 require.Zero(m.TimeUntil(now, actualVal+.1)) 166 }