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  }