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  }