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 }