github.com/uber-go/tally/v4@v4.1.17/histogram_test.go (about) 1 // Copyright (c) 2021 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package tally 22 23 import ( 24 "math" 25 "testing" 26 "time" 27 28 "github.com/stretchr/testify/assert" 29 "github.com/stretchr/testify/require" 30 ) 31 32 func TestValueBucketsString(t *testing.T) { 33 result, err := LinearValueBuckets(1, 1, 3) 34 require.NoError(t, err) 35 assert.Equal(t, "[1.000000 2.000000 3.000000]", Buckets(result).String()) 36 } 37 38 func TestDurationBucketsString(t *testing.T) { 39 result, err := LinearDurationBuckets(time.Second, time.Second, 3) 40 require.NoError(t, err) 41 assert.Equal(t, "[1s 2s 3s]", Buckets(result).String()) 42 } 43 44 func TestBucketPairsDefaultsToNegInfinityToInfinity(t *testing.T) { 45 pairs := BucketPairs(nil) 46 require.Equal(t, 1, len(pairs)) 47 48 assert.Equal(t, -math.MaxFloat64, pairs[0].LowerBoundValue()) 49 assert.Equal(t, math.MaxFloat64, pairs[0].UpperBoundValue()) 50 51 assert.Equal(t, time.Duration(math.MinInt64), pairs[0].LowerBoundDuration()) 52 assert.Equal(t, time.Duration(math.MaxInt64), pairs[0].UpperBoundDuration()) 53 } 54 55 func TestBucketPairsSortsValueBuckets(t *testing.T) { 56 pairs := BucketPairs(ValueBuckets{1.0, 3.0, 2.0}) 57 require.Equal(t, 4, len(pairs)) 58 59 assert.Equal(t, -math.MaxFloat64, pairs[0].LowerBoundValue()) 60 assert.Equal(t, 1.0, pairs[0].UpperBoundValue()) 61 62 assert.Equal(t, 1.0, pairs[1].LowerBoundValue()) 63 assert.Equal(t, 2.0, pairs[1].UpperBoundValue()) 64 65 assert.Equal(t, 2.0, pairs[2].LowerBoundValue()) 66 assert.Equal(t, 3.0, pairs[2].UpperBoundValue()) 67 68 assert.Equal(t, 3.0, pairs[3].LowerBoundValue()) 69 assert.Equal(t, math.MaxFloat64, pairs[3].UpperBoundValue()) 70 } 71 72 func TestBucketPairsSortsDurationBuckets(t *testing.T) { 73 pairs := BucketPairs(DurationBuckets{0 * time.Second, 2 * time.Second, 1 * time.Second}) 74 require.Equal(t, 4, len(pairs)) 75 76 assert.Equal(t, time.Duration(math.MinInt64), pairs[0].LowerBoundDuration()) 77 assert.Equal(t, 0*time.Second, pairs[0].UpperBoundDuration()) 78 79 assert.Equal(t, 0*time.Second, pairs[1].LowerBoundDuration()) 80 assert.Equal(t, 1*time.Second, pairs[1].UpperBoundDuration()) 81 82 assert.Equal(t, 1*time.Second, pairs[2].LowerBoundDuration()) 83 assert.Equal(t, 2*time.Second, pairs[2].UpperBoundDuration()) 84 85 assert.Equal(t, 2*time.Second, pairs[3].LowerBoundDuration()) 86 assert.Equal(t, time.Duration(math.MaxInt64), pairs[3].UpperBoundDuration()) 87 } 88 89 func TestMustMakeLinearValueBuckets(t *testing.T) { 90 assert.NotPanics(t, func() { 91 assert.Equal(t, ValueBuckets{ 92 0.0, 1.0, 2.0, 93 }, MustMakeLinearValueBuckets(0, 1, 3)) 94 }) 95 } 96 97 func TestMustMakeLinearValueBucketsPanicsOnBadCount(t *testing.T) { 98 assert.Panics(t, func() { 99 MustMakeLinearValueBuckets(0, 1, 0) 100 }) 101 } 102 103 func TestMustMakeLinearDurationBuckets(t *testing.T) { 104 assert.NotPanics(t, func() { 105 assert.Equal(t, DurationBuckets{ 106 0, time.Second, 2 * time.Second, 107 }, MustMakeLinearDurationBuckets(0*time.Second, 1*time.Second, 3)) 108 }) 109 } 110 111 func TestMustMakeLinearDurationBucketsPanicsOnBadCount(t *testing.T) { 112 assert.Panics(t, func() { 113 MustMakeLinearDurationBuckets(0*time.Second, 1*time.Second, 0) 114 }) 115 } 116 117 func TestMustMakeExponentialValueBuckets(t *testing.T) { 118 assert.NotPanics(t, func() { 119 assert.Equal(t, ValueBuckets{ 120 2, 4, 8, 121 }, MustMakeExponentialValueBuckets(2, 2, 3)) 122 }) 123 } 124 125 func TestMustMakeExponentialValueBucketsPanicsOnBadCount(t *testing.T) { 126 assert.Panics(t, func() { 127 MustMakeExponentialValueBuckets(2, 2, 0) 128 }) 129 } 130 131 func TestMustMakeExponentialValueBucketsPanicsOnBadStart(t *testing.T) { 132 assert.Panics(t, func() { 133 MustMakeExponentialValueBuckets(0, 2, 2) 134 }) 135 } 136 137 func TestMustMakeExponentialValueBucketsPanicsOnBadFactor(t *testing.T) { 138 assert.Panics(t, func() { 139 MustMakeExponentialValueBuckets(2, 1, 2) 140 }) 141 } 142 143 func TestMustMakeExponentialDurationBuckets(t *testing.T) { 144 assert.NotPanics(t, func() { 145 assert.Equal(t, DurationBuckets{ 146 2 * time.Second, 4 * time.Second, 8 * time.Second, 147 }, MustMakeExponentialDurationBuckets(2*time.Second, 2, 3)) 148 }) 149 } 150 151 func TestMustMakeExponentialDurationBucketsPanicsOnBadCount(t *testing.T) { 152 assert.Panics(t, func() { 153 MustMakeExponentialDurationBuckets(2*time.Second, 2, 0) 154 }) 155 } 156 157 func TestMustMakeExponentialDurationBucketsPanicsOnBadStart(t *testing.T) { 158 assert.Panics(t, func() { 159 MustMakeExponentialDurationBuckets(0, 2, 2) 160 }) 161 } 162 163 func TestMustMakeExponentialDurationBucketsPanicsOnBadFactor(t *testing.T) { 164 assert.Panics(t, func() { 165 MustMakeExponentialDurationBuckets(2*time.Second, 1, 2) 166 }) 167 } 168 169 func TestBucketPairsNoRaceWhenSorted(t *testing.T) { 170 buckets := DurationBuckets{} 171 for i := 0; i < 99; i++ { 172 buckets = append(buckets, time.Duration(i)*time.Second) 173 } 174 newPair := func() { 175 pairs := BucketPairs(buckets) 176 require.Equal(t, 100, len(pairs)) 177 } 178 for i := 0; i < 10; i++ { 179 go newPair() 180 } 181 } 182 183 func TestBucketPairsNoRaceWhenUnsorted(t *testing.T) { 184 buckets := DurationBuckets{} 185 for i := 100; i > 1; i-- { 186 buckets = append(buckets, time.Duration(i)*time.Second) 187 } 188 newPair := func() { 189 pairs := BucketPairs(buckets) 190 require.Equal(t, 100, len(pairs)) 191 } 192 for i := 0; i < 10; i++ { 193 go newPair() 194 } 195 } 196 197 func BenchmarkBucketsEqual(b *testing.B) { 198 bench := func(b *testing.B, x Buckets, y Buckets) { 199 b.ResetTimer() 200 201 for i := 0; i < b.N; i++ { 202 bucketsEqual(x, y) 203 } 204 } 205 206 b.Run("same 20 values", func(b *testing.B) { 207 buckets := MustMakeLinearValueBuckets(1.0, 1.0, 20) 208 bench(b, buckets, buckets) 209 }) 210 211 b.Run("same 20 durations", func(b *testing.B) { 212 buckets := MustMakeLinearDurationBuckets(time.Second, time.Second, 20) 213 bench(b, buckets, buckets) 214 }) 215 }