github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/functions/aggregation/base_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 "time" 27 28 "github.com/m3db/m3/src/query/block" 29 "github.com/m3db/m3/src/query/executor/transform" 30 "github.com/m3db/m3/src/query/models" 31 "github.com/m3db/m3/src/query/parser" 32 "github.com/m3db/m3/src/query/test" 33 "github.com/m3db/m3/src/query/test/compare" 34 "github.com/m3db/m3/src/query/test/executor" 35 xtime "github.com/m3db/m3/src/x/time" 36 37 "github.com/stretchr/testify/assert" 38 "github.com/stretchr/testify/require" 39 ) 40 41 var ( 42 seriesMetas = []block.SeriesMeta{ 43 {Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "1"}, {N: "d", V: "4"}})}, 44 {Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "1"}, {N: "d", V: "4"}})}, 45 {Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "1"}, {N: "b", V: "2"}, {N: "d", V: "4"}})}, 46 {Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "2"}, {N: "b", V: "2"}, {N: "d", V: "4"}})}, 47 {Tags: test.StringTagsToTags(test.StringTags{{N: "b", V: "2"}, {N: "d", V: "4"}})}, 48 {Tags: test.StringTagsToTags(test.StringTags{{N: "c", V: "3"}, {N: "d", V: "4"}})}, 49 } 50 v = [][]float64{ 51 {0, math.NaN(), 2, 3, 4}, 52 {math.NaN(), 6, 7, 8, 9}, 53 {10, 20, 30, 40, 50}, 54 {50, 60, 70, 80, 90}, 55 {100, 200, 300, 400, 500}, 56 {600, 700, 800, 900, 1000}, 57 } 58 59 bounds = models.Bounds{ 60 Start: xtime.Now(), 61 Duration: time.Minute * 5, 62 StepSize: time.Minute, 63 } 64 65 typeBytes = []byte(StandardDeviationType) 66 ) 67 68 func processAggregationOp(t *testing.T, op parser.Params) *executor.SinkNode { 69 bl := test.NewBlockFromValuesWithSeriesMeta(bounds, seriesMetas, v) 70 c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1))) 71 node := op.(baseOp).Node(c, transform.Options{}) 72 err := node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), bl) 73 require.NoError(t, err) 74 return sink 75 } 76 77 func TestFunctionFilteringWithA(t *testing.T) { 78 op, err := NewAggregationOp(StandardDeviationType, NodeParams{ 79 MatchingTags: [][]byte{[]byte("a")}, Without: false, 80 }) 81 require.NoError(t, err) 82 sink := processAggregationOp(t, op) 83 expected := [][]float64{ 84 // stddev of fifth and sixth series 85 {250, 250, 250, 250, 250}, 86 // stddev of first three series 87 {5, 7, 12.19289, 16.39105, 20.60744}, 88 // stddev of fourth series 89 {0, 0, 0, 0, 0}, 90 } 91 92 expectedMetas := []block.SeriesMeta{ 93 {Name: typeBytes, Tags: models.EmptyTags()}, 94 {Name: typeBytes, Tags: test.TagSliceToTags([]models.Tag{{Name: []byte("a"), Value: []byte("1")}})}, 95 {Name: typeBytes, Tags: test.TagSliceToTags([]models.Tag{{Name: []byte("a"), Value: []byte("2")}})}, 96 } 97 expectedMetaTags := models.EmptyTags() 98 99 compare.CompareValuesInOrder(t, sink.Metas, expectedMetas, sink.Values, expected) 100 assert.Equal(t, bounds, sink.Meta.Bounds) 101 assert.Equal(t, expectedMetaTags.Tags, sink.Meta.Tags.Tags) 102 } 103 104 func TestFunctionFilteringWithoutA(t *testing.T) { 105 op, err := NewAggregationOp(StandardDeviationType, NodeParams{ 106 MatchingTags: [][]byte{[]byte("a")}, Without: true, 107 }) 108 require.NoError(t, err) 109 sink := processAggregationOp(t, op) 110 expected := [][]float64{ 111 // stddev of third, fourth, and fifth series 112 {36.81787, 77.17225, 118.97712, 161.10728, 203.36065}, 113 // stddev of sixth series 114 {0, 0, 0, 0, 0}, 115 // stddev of first two series 116 {0, 0, 2.5, 2.5, 2.5}, 117 } 118 119 expectedMetas := []block.SeriesMeta{ 120 {Name: typeBytes, Tags: test.TagSliceToTags([]models.Tag{{Name: []byte("b"), Value: []byte("2")}})}, 121 {Name: typeBytes, Tags: test.TagSliceToTags([]models.Tag{{Name: []byte("c"), Value: []byte("3")}})}, 122 {Name: typeBytes, Tags: models.EmptyTags()}, 123 } 124 125 expectedMetaTags := test.TagSliceToTags([]models.Tag{{Name: []byte("d"), Value: []byte("4")}}) 126 compare.CompareValuesInOrder(t, sink.Metas, expectedMetas, sink.Values, expected) 127 assert.Equal(t, bounds, sink.Meta.Bounds) 128 assert.Equal(t, expectedMetaTags.Tags, sink.Meta.Tags.Tags) 129 } 130 131 func TestFunctionFilteringWithD(t *testing.T) { 132 op, err := NewAggregationOp(StandardDeviationType, NodeParams{ 133 MatchingTags: [][]byte{[]byte("d")}, Without: false, 134 }) 135 require.NoError(t, err) 136 sink := processAggregationOp(t, op) 137 expected := [][]float64{ 138 // stddev of all series 139 {226.75096, 260.61343, 286.42611, 325.77587, 366.35491}, 140 } 141 142 expectedMetas := []block.SeriesMeta{ 143 {Name: typeBytes, Tags: models.EmptyTags()}, 144 } 145 146 expectedMetaTags := test.TagSliceToTags([]models.Tag{{Name: []byte("d"), Value: []byte("4")}}) 147 compare.CompareValuesInOrder(t, sink.Metas, expectedMetas, sink.Values, expected) 148 assert.Equal(t, bounds, sink.Meta.Bounds) 149 assert.Equal(t, expectedMetaTags.Tags, sink.Meta.Tags.Tags) 150 } 151 152 func TestFunctionFilteringWithoutD(t *testing.T) { 153 op, err := NewAggregationOp(StandardDeviationType, NodeParams{ 154 MatchingTags: [][]byte{[]byte("d")}, Without: true, 155 }) 156 require.NoError(t, err) 157 sink := processAggregationOp(t, op) 158 159 expected := [][]float64{ 160 // stddev of first two series 161 {0, 0, 2.5, 2.5, 2.5}, 162 // stddev of third series 163 {0, 0, 0, 0, 0}, 164 // stddev of fourth series 165 {0, 0, 0, 0, 0}, 166 // stddev of fifth series 167 {0, 0, 0, 0, 0}, 168 // stddev of sixth series 169 {0, 0, 0, 0, 0}, 170 } 171 172 expectedMetas := []block.SeriesMeta{ 173 {Name: typeBytes, Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "1"}})}, 174 {Name: typeBytes, Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "1"}, {N: "b", V: "2"}})}, 175 {Name: typeBytes, Tags: test.StringTagsToTags(test.StringTags{{N: "a", V: "2"}, {N: "b", V: "2"}})}, 176 {Name: typeBytes, Tags: test.StringTagsToTags(test.StringTags{{N: "b", V: "2"}})}, 177 {Name: typeBytes, Tags: test.StringTagsToTags(test.StringTags{{N: "c", V: "3"}})}, 178 } 179 expectedMetaTags := models.EmptyTags() 180 181 compare.CompareValuesInOrder(t, sink.Metas, expectedMetas, sink.Values, expected) 182 assert.Equal(t, bounds, sink.Meta.Bounds) 183 assert.Equal(t, expectedMetaTags.Tags, sink.Meta.Tags.Tags) 184 }