github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/functions/temporal/aggregation_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 temporal
    22  
    23  import (
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/m3db/m3/src/query/executor/transform"
    28  
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  var aggregationTestCases = []testCase{
    33  	{
    34  		name:   "avg_over_time",
    35  		opType: AvgType,
    36  		vals: [][]float64{
    37  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
    38  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
    39  		},
    40  		expected: [][]float64{
    41  			{nan, 1, 1.5, 2, 2.5, 2, 2, 2, 2, 2},
    42  			{5, 5.5, 6, 6.5, 7, 7, 7, 7, 7, 7},
    43  		},
    44  	},
    45  	{
    46  		name:   "avg_over_time with warning",
    47  		opType: AvgType,
    48  		vals: [][]float64{
    49  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
    50  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
    51  		},
    52  		expected: [][]float64{
    53  			{nan, 1, 1.5, 2, 2.5, 2, 2, 2, 2, 2},
    54  			{5, 5.5, 6, 6.5, 7, 7, 7, 7, 7, 7},
    55  		},
    56  		withWarning: true,
    57  	},
    58  	{
    59  		name:   "avg_over_time all NaNs",
    60  		opType: AvgType,
    61  		vals: [][]float64{
    62  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    63  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    64  		},
    65  		expected: [][]float64{
    66  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    67  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    68  		},
    69  	},
    70  	{
    71  		name:   "count_over_time",
    72  		opType: CountType,
    73  		vals: [][]float64{
    74  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
    75  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
    76  		},
    77  		expected: [][]float64{
    78  			{nan, 1, 2, 3, 4, 5, 5, 5, 5, 5},
    79  			{1, 2, 3, 4, 5, 5, 5, 5, 5, 5},
    80  		},
    81  	},
    82  	{
    83  		name:   "count_over_time all NaNs",
    84  		opType: CountType,
    85  		vals: [][]float64{
    86  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    87  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    88  		},
    89  		expected: [][]float64{
    90  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    91  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
    92  		},
    93  	},
    94  	{
    95  		name:   "min_over_time",
    96  		opType: MinType,
    97  		vals: [][]float64{
    98  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
    99  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 1},
   100  		},
   101  		expected: [][]float64{
   102  			{nan, 1, 1, 1, 1, 0, 0, 0, 0, 0},
   103  			{5, 5, 5, 5, 5, 5, 5, 5, 5, 1},
   104  		},
   105  	},
   106  	{
   107  		name:   "min_over_time all NaNs",
   108  		opType: MinType,
   109  		vals: [][]float64{
   110  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   111  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   112  		},
   113  		expected: [][]float64{
   114  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   115  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   116  		},
   117  	},
   118  	{
   119  		name:   "max_over_time",
   120  		opType: MaxType,
   121  		vals: [][]float64{
   122  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   123  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 111},
   124  		},
   125  		expected: [][]float64{
   126  			{nan, 1, 2, 3, 4, 4, 4, 4, 4, 4},
   127  			{5, 6, 7, 8, 9, 9, 9, 9, 9, 111},
   128  		},
   129  	},
   130  	{
   131  		name:   "max_over_time all NaNs",
   132  		opType: MaxType,
   133  		vals: [][]float64{
   134  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   135  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   136  		},
   137  		expected: [][]float64{
   138  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   139  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   140  		},
   141  	},
   142  	{
   143  		name:   "sum_over_time",
   144  		opType: SumType,
   145  		vals: [][]float64{
   146  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   147  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
   148  		},
   149  		expected: [][]float64{
   150  			{nan, 1, 3, 6, 10, 10, 10, 10, 10, 10},
   151  			{5, 11, 18, 26, 35, 35, 35, 35, 35, 35},
   152  		},
   153  	},
   154  	{
   155  		name:   "sum_over_time all NaNs",
   156  		opType: SumType,
   157  		vals: [][]float64{
   158  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   159  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   160  		},
   161  		expected: [][]float64{
   162  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   163  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   164  		},
   165  	},
   166  	{
   167  		name:   "stddev_over_time",
   168  		opType: StdDevType,
   169  		vals: [][]float64{
   170  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   171  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
   172  		},
   173  		expected: [][]float64{
   174  			{nan, nan, 0.5, 0.81649, 1.1180,
   175  				1.4142, 1.4142, 1.4142, 1.4142, 1.4142},
   176  			{nan, 0.5, 0.81649, 1.11803, 1.4142,
   177  				1.4142, 1.4142, 1.4142, 1.4142, 1.4142},
   178  		},
   179  	},
   180  	{
   181  		name:   "stddev_over_time all NaNs",
   182  		opType: StdDevType,
   183  		vals: [][]float64{
   184  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   185  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   186  		},
   187  		expected: [][]float64{
   188  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   189  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   190  		},
   191  	},
   192  	{
   193  		name:   "stdvar_over_time",
   194  		opType: StdVarType,
   195  		vals: [][]float64{
   196  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   197  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
   198  		},
   199  		expected: [][]float64{
   200  			{nan, nan, 0.25, 0.666666, 1.25, 2, 2, 2, 2, 2},
   201  			{nan, 0.25, 0.66666, 1.25, 2, 2, 2, 2, 2, 2},
   202  		},
   203  	},
   204  	{
   205  		name:   "stdvar_over_time all NaNs",
   206  		opType: StdVarType,
   207  		vals: [][]float64{
   208  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   209  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   210  		},
   211  		expected: [][]float64{
   212  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   213  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   214  		},
   215  	},
   216  	{
   217  		name:   "last_over_time",
   218  		opType: LastType,
   219  		vals: [][]float64{
   220  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   221  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
   222  		},
   223  		expected: [][]float64{
   224  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   225  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
   226  		},
   227  	},
   228  	{
   229  		name:   "last_over_time leading NaNs",
   230  		opType: LastType,
   231  		vals: [][]float64{
   232  			{nan, 1, nan, 3, nan, nan, 2, nan, nan, nan},
   233  			{5, nan, nan, nan, nan, nan, nan, 7, nan, nan},
   234  		},
   235  		expected: [][]float64{
   236  			{nan, 1, nan, 3, nan, nan, 2, nan, nan, nan},
   237  			{5, nan, nan, nan, nan, nan, nan, 7, nan, nan},
   238  		},
   239  	},
   240  	{
   241  		name:   "last_over_time all NaNs",
   242  		opType: LastType,
   243  		vals: [][]float64{
   244  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   245  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   246  		},
   247  		expected: [][]float64{
   248  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   249  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   250  		},
   251  	},
   252  	{
   253  		name:   "quantile_over_time",
   254  		opType: QuantileType,
   255  		vals: [][]float64{
   256  			{nan, 1, 2, 3, 4, 0, 1, 2, 3, 4},
   257  			{5, 6, 7, 8, 9, 5, 6, 7, 8, 9},
   258  		},
   259  		expected: [][]float64{
   260  			{nan, 1, 1.2, 1.4, 1.6, 0.8, 0.8, 0.8, 0.8, 0.8},
   261  			{5, 5.2, 5.4, 5.6, 5.8, 5.8, 5.8, 5.8, 5.8, 5.8},
   262  		},
   263  	},
   264  	{
   265  		name:   "quantile_over_time all NaNs",
   266  		opType: QuantileType,
   267  		vals: [][]float64{
   268  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   269  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   270  		},
   271  		expected: [][]float64{
   272  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   273  			{nan, nan, nan, nan, nan, nan, nan, nan, nan, nan},
   274  		},
   275  	},
   276  }
   277  
   278  func TestAggregation(t *testing.T) {
   279  	opGen := func(t *testing.T, tc testCase) transform.Params {
   280  		if tc.opType == QuantileType {
   281  			args := []interface{}{0.2, 5 * time.Minute}
   282  			baseOp, err := NewQuantileOp(args, tc.opType)
   283  			require.NoError(t, err)
   284  
   285  			return baseOp
   286  		}
   287  
   288  		args := []interface{}{5 * time.Minute}
   289  		baseOp, err := NewAggOp(args, tc.opType)
   290  		require.NoError(t, err)
   291  		return baseOp
   292  	}
   293  
   294  	testTemporalFunc(t, opGen, aggregationTestCases)
   295  }
   296  
   297  func TestUnknownAggregation(t *testing.T) {
   298  	_, err := NewAggOp([]interface{}{5 * time.Minute}, "unknown_agg_func")
   299  	require.Error(t, err)
   300  }