github.com/m3db/m3@v1.5.0/src/query/functions/aggregation/function_test.go (about)

     1  // Copyright (c) 2018 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 aggregation
    22  
    23  import (
    24  	"math"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  
    29  	"github.com/m3db/m3/src/query/test/compare"
    30  )
    31  
    32  type funcTest struct {
    33  	name     string
    34  	fn       aggregationFn
    35  	expected []float64
    36  }
    37  
    38  var nan = math.NaN()
    39  
    40  var fnTest = []struct {
    41  	name      string
    42  	values    []float64
    43  	buckets   [][]int
    44  	functions []funcTest
    45  }{
    46  	{
    47  		"empty", []float64{}, [][]int{}, []funcTest{
    48  			{SumType, sumFn, []float64{}},
    49  			{MinType, minFn, []float64{}},
    50  			{MaxType, maxFn, []float64{}},
    51  			{AverageType, averageFn, []float64{}},
    52  			{StandardDeviationType, stddevFn, []float64{}},
    53  			{StandardVarianceType, varianceFn, []float64{}},
    54  			{CountType, countFn, []float64{}},
    55  		},
    56  	},
    57  	{
    58  		"one value", []float64{1.5}, [][]int{{0}}, []funcTest{
    59  			{SumType, sumFn, []float64{1.5}},
    60  			{MinType, minFn, []float64{1.5}},
    61  			{MaxType, maxFn, []float64{1.5}},
    62  			{AverageType, averageFn, []float64{1.5}},
    63  			{StandardDeviationType, stddevFn, []float64{0}},
    64  			{StandardVarianceType, varianceFn, []float64{0}},
    65  			{CountType, countFn, []float64{1}},
    66  		},
    67  	},
    68  	{
    69  		"two values, one index", []float64{1.5, 2.6}, [][]int{{0, 1}}, []funcTest{
    70  			{SumType, sumFn, []float64{4.1}},
    71  			{MinType, minFn, []float64{1.5}},
    72  			{MaxType, maxFn, []float64{2.6}},
    73  			{AverageType, averageFn, []float64{2.05}},
    74  			{StandardDeviationType, stddevFn, []float64{0.55}},
    75  			{StandardVarianceType, varianceFn, []float64{0.3025}},
    76  			{CountType, countFn, []float64{2}},
    77  		},
    78  	},
    79  	{
    80  		"two values, two index", []float64{1.5, 2.6}, [][]int{{0}, {1}}, []funcTest{
    81  			{SumType, sumFn, []float64{1.5, 2.6}},
    82  			{MinType, minFn, []float64{1.5, 2.6}},
    83  			{MaxType, maxFn, []float64{1.5, 2.6}},
    84  			{AverageType, averageFn, []float64{1.5, 2.6}},
    85  			{StandardDeviationType, stddevFn, []float64{0, 0}},
    86  			{StandardVarianceType, varianceFn, []float64{0, 0}},
    87  			{CountType, countFn, []float64{1, 1}},
    88  		},
    89  	},
    90  	{
    91  		"many values, one index", []float64{10, 8, 10, 8, 8, 4}, [][]int{{0, 1, 2, 3, 4, 5}}, []funcTest{
    92  			{SumType, sumFn, []float64{48}},
    93  			{MinType, minFn, []float64{4}},
    94  			{MaxType, maxFn, []float64{10}},
    95  			{AverageType, averageFn, []float64{8}},
    96  			{StandardDeviationType, stddevFn, []float64{2}},
    97  			{StandardVarianceType, varianceFn, []float64{4}},
    98  			{CountType, countFn, []float64{6}},
    99  		},
   100  	},
   101  	{
   102  		"many values, many indices",
   103  		[]float64{10, 17, 8, 1.5, 10, -3, 8, 100, 8, 0, 4, -0.5},
   104  		[][]int{{0, 2, 4, 6, 8, 10}, {1, 3, 5, 7, 9, 11}},
   105  		[]funcTest{
   106  			{SumType, sumFn, []float64{48, 115}},
   107  			{MinType, minFn, []float64{4, -3}},
   108  			{MaxType, maxFn, []float64{10, 100}},
   109  			{AverageType, averageFn, []float64{8, 19.16666}},
   110  			{StandardDeviationType, stddevFn, []float64{2, 36.73403}},
   111  			{StandardVarianceType, varianceFn, []float64{4, 1349.38889}},
   112  			{CountType, countFn, []float64{6, 6}},
   113  		},
   114  	},
   115  	{
   116  		"many values, one index, with nans",
   117  		[]float64{10, nan, 10, nan, 8, 4},
   118  		[][]int{{0, 1, 2, 3, 4, 5}}, []funcTest{
   119  			{SumType, sumFn, []float64{32}},
   120  			{MinType, minFn, []float64{4}},
   121  			{MaxType, maxFn, []float64{10}},
   122  			{AverageType, averageFn, []float64{8}},
   123  			{StandardDeviationType, stddevFn, []float64{2.44949}},
   124  			{StandardVarianceType, varianceFn, []float64{6}},
   125  			{CountType, countFn, []float64{4}},
   126  			{AbsentType, absentFn, []float64{nan}},
   127  		},
   128  	},
   129  	{
   130  		"only nans",
   131  		[]float64{nan, nan, nan, nan},
   132  		[][]int{{0, 1, 2, 3}}, []funcTest{
   133  			{SumType, sumFn, []float64{nan}},
   134  			{MinType, minFn, []float64{nan}},
   135  			{MaxType, maxFn, []float64{nan}},
   136  			{AverageType, averageFn, []float64{nan}},
   137  			{StandardDeviationType, stddevFn, []float64{nan}},
   138  			{StandardVarianceType, varianceFn, []float64{nan}},
   139  			{CountType, countFn, []float64{0}},
   140  			{AbsentType, absentFn, []float64{1}},
   141  		},
   142  	},
   143  	{
   144  		"verified population deviations",
   145  		[]float64{9, 2, 5, 4, 12, 7, 8, 11, 9, 3, 7, 4, 12, 5, 4, 10, 9, 6, 9, 4},
   146  		[][]int{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}}, []funcTest{
   147  			{StandardDeviationType, stddevFn, []float64{2.98329}},
   148  			{StandardVarianceType, varianceFn, []float64{8.9}},
   149  		},
   150  	},
   151  }
   152  
   153  func TestAggFns(t *testing.T) {
   154  	for _, tt := range fnTest {
   155  		for _, function := range tt.functions {
   156  			t.Run(tt.name+" "+function.name, func(t *testing.T) {
   157  				for i, bucket := range tt.buckets {
   158  					actual := function.fn(tt.values, bucket)
   159  					expected := function.expected[i]
   160  					compare.EqualsWithNansWithDelta(t, expected, actual, math.Pow10(-5))
   161  				}
   162  			})
   163  		}
   164  	}
   165  }
   166  
   167  var equalValuePrecisionTest = []struct {
   168  	name   string
   169  	values []float64
   170  }{
   171  	{
   172  		"five 1.33e-5",
   173  		[]float64{1.33e-5, 1.33e-5, 1.33e-5, 1.33e-5, 1.33e-5},
   174  	},
   175  	{
   176  		"three 13.3",
   177  		[]float64{13.3, 13.3, 13.3},
   178  	},
   179  }
   180  
   181  func TestVarianceFnEqualValuePrecision(t *testing.T) {
   182  	for _, tt := range equalValuePrecisionTest {
   183  		t.Run(tt.name, func(t *testing.T) {
   184  			bucket := make([]int, len(tt.values))
   185  			for i := range bucket {
   186  				bucket[i] = i
   187  			}
   188  
   189  			assert.Equal(t, 0.0, varianceFn(tt.values, bucket))
   190  		})
   191  	}
   192  }
   193  
   194  func TestStddevFnEqualValuePrecision(t *testing.T) {
   195  	for _, tt := range equalValuePrecisionTest {
   196  		t.Run(tt.name, func(t *testing.T) {
   197  			bucket := make([]int, len(tt.values))
   198  			for i := range bucket {
   199  				bucket[i] = i
   200  			}
   201  
   202  			assert.Equal(t, 0.0, stddevFn(tt.values, bucket))
   203  		})
   204  	}
   205  }