github.com/go-graphite/carbonapi@v0.17.0/expr/functions/highestLowest/function_test.go (about)

     1  package highestLowest
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/go-graphite/carbonapi/expr/interfaces"
     9  	"github.com/go-graphite/carbonapi/expr/metadata"
    10  	"github.com/go-graphite/carbonapi/expr/types"
    11  	"github.com/go-graphite/carbonapi/pkg/parser"
    12  	th "github.com/go-graphite/carbonapi/tests"
    13  )
    14  
    15  var (
    16  	md []interfaces.FunctionMetadata = New("")
    17  )
    18  
    19  func init() {
    20  	for _, m := range md {
    21  		metadata.RegisterFunction(m.Name, m.F)
    22  	}
    23  }
    24  
    25  func TestHighestMultiReturn(t *testing.T) {
    26  	now32 := int64(time.Now().Unix())
    27  
    28  	tests := []th.MultiReturnEvalTestItem{
    29  		{
    30  			"highestCurrent(metric1,2)",
    31  			map[parser.MetricRequest][]*types.MetricData{
    32  				{Metric: "metric1", From: 0, Until: 1}: {
    33  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
    34  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
    35  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
    36  				},
    37  			},
    38  			"highestCurrent",
    39  			map[string][]*types.MetricData{
    40  				"metricA": {types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32)},
    41  				"metricC": {types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32)},
    42  			},
    43  		},
    44  		{
    45  			"highestCurrent(metric1)",
    46  			map[parser.MetricRequest][]*types.MetricData{
    47  				parser.MetricRequest{Metric: "metric1", From: 0, Until: 1}: {
    48  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
    49  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
    50  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
    51  				},
    52  			},
    53  			"highestCurrent",
    54  			map[string][]*types.MetricData{
    55  				"metricC": {types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32)},
    56  			},
    57  		},
    58  		{
    59  			"highestMax(metric1, 2)",
    60  			map[parser.MetricRequest][]*types.MetricData{
    61  				parser.MetricRequest{Metric: "metric1", From: 0, Until: 1}: {
    62  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12, 9}, 1, now32),
    63  					types.MakeMetricData("metricB", []float64{1, 5, 5, 5, 5, 5, 3}, 1, now32),
    64  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10, 10}, 1, now32),
    65  				},
    66  			},
    67  			"highestMax",
    68  			map[string][]*types.MetricData{
    69  				"metricA": {types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12, 9}, 1, now32)},
    70  				"metricC": {types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10, 10}, 1, now32)},
    71  			},
    72  		},
    73  		{
    74  			"highestMin(metric1, 2)",
    75  			map[parser.MetricRequest][]*types.MetricData{
    76  				parser.MetricRequest{Metric: "metric1", From: 0, Until: 1}: {
    77  					types.MakeMetricData("metricA", []float64{6, 1, 3, 3, 4, 12}, 1, now32),
    78  					types.MakeMetricData("metricB", []float64{2, 5, 5, 5, 5, 5}, 1, now32),
    79  					types.MakeMetricData("metricC", []float64{3, 2, 3, 3, 4, 10}, 1, now32),
    80  				},
    81  			},
    82  			"highestMin",
    83  			map[string][]*types.MetricData{
    84  				"metricB": {types.MakeMetricData("metricB", []float64{2, 5, 5, 5, 5, 5}, 1, now32)},
    85  				"metricC": {types.MakeMetricData("metricC", []float64{3, 2, 3, 3, 4, 10}, 1, now32)},
    86  			},
    87  		},
    88  		{
    89  			"highest(metric1, 2, \"max\")",
    90  			map[parser.MetricRequest][]*types.MetricData{
    91  				{Metric: "metric1", From: 0, Until: 1}: {
    92  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
    93  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
    94  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
    95  				},
    96  			},
    97  			"highest",
    98  			map[string][]*types.MetricData{
    99  				"metricA": {types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32)},
   100  				"metricC": {types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32)},
   101  			},
   102  		},
   103  		{
   104  			"lowest(metric1, 2, \"max\")",
   105  			map[parser.MetricRequest][]*types.MetricData{
   106  				{Metric: "metric1", From: 0, Until: 1}: {
   107  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
   108  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   109  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   110  				},
   111  			},
   112  			"lowest",
   113  			map[string][]*types.MetricData{
   114  				"metricB": {types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32)},
   115  				"metricC": {types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32)},
   116  			},
   117  		},
   118  
   119  		{
   120  			"lowestCurrent(metric1,3)",
   121  			map[parser.MetricRequest][]*types.MetricData{
   122  				{Metric: "metric1", From: 0, Until: 1}: {
   123  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   124  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   125  					types.MakeMetricData("metricD", []float64{1, 1, 3, 3, 4, 3}, 1, now32),
   126  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   127  				},
   128  			},
   129  			"lowestCurrent",
   130  			map[string][]*types.MetricData{
   131  				"metricA": {types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32)},
   132  				"metricB": {types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32)},
   133  				"metricD": {types.MakeMetricData("metricD", []float64{1, 1, 3, 3, 4, 3}, 1, now32)},
   134  			},
   135  		},
   136  		{
   137  			"lowestCurrent(metric1)",
   138  			map[parser.MetricRequest][]*types.MetricData{
   139  				parser.MetricRequest{Metric: "metric1", From: 0, Until: 1}: {
   140  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   141  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   142  					types.MakeMetricData("metricD", []float64{1, 1, 3, 3, 4, 3}, 1, now32),
   143  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   144  				},
   145  			},
   146  			"lowestCurrent",
   147  			map[string][]*types.MetricData{
   148  				"metricB": {types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32)},
   149  			},
   150  		},
   151  	}
   152  
   153  	for _, tt := range tests {
   154  		testName := tt.Target
   155  		t.Run(testName, func(t *testing.T) {
   156  			eval := th.EvaluatorFromFunc(md[0].F)
   157  			th.TestMultiReturnEvalExpr(t, eval, &tt)
   158  		})
   159  	}
   160  }
   161  
   162  func TestHighest(t *testing.T) {
   163  	now32 := int64(time.Now().Unix())
   164  
   165  	tests := []th.EvalTestItem{
   166  		{
   167  			"highestCurrent(metric1,1)",
   168  			map[parser.MetricRequest][]*types.MetricData{
   169  				{Metric: "metric1", From: 0, Until: 1}: {
   170  					types.MakeMetricData("metric0", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN()}, 1, now32),
   171  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   172  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   173  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   174  				},
   175  			},
   176  			[]*types.MetricData{types.MakeMetricData("metricC", // NOTE(dgryski): not sure if this matches graphite
   177  				[]float64{1, 1, 3, 3, 4, 15}, 1, now32)},
   178  		},
   179  		{
   180  			"highestCurrent(metric1,4)",
   181  			map[parser.MetricRequest][]*types.MetricData{
   182  				{Metric: "metric1", From: 0, Until: 1}: {
   183  					types.MakeMetricData("metric0", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN()}, 1, now32),
   184  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   185  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   186  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   187  				},
   188  			},
   189  			[]*types.MetricData{
   190  				types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   191  				types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   192  				types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   193  				//NOTE(nnuss): highest* functions filter null-valued series as a side-effect when `n` >= number of series
   194  				//TODO(nnuss): bring lowest* functions into harmony with this side effect or get rid of it
   195  				//types.MakeMetricData("metric0", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN()}, 1, now32),
   196  			},
   197  		},
   198  		{
   199  			"highestAverage(metric1,1)",
   200  			map[parser.MetricRequest][]*types.MetricData{
   201  				{Metric: "metric1", From: 0, Until: 1}: {
   202  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   203  					types.MakeMetricData("metricB", []float64{1, 5, 5, 5, 5, 5}, 1, now32),
   204  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   205  				},
   206  			},
   207  			[]*types.MetricData{types.MakeMetricData("metricB", // NOTE(dgryski): not sure if this matches graphite
   208  				[]float64{1, 5, 5, 5, 5, 5}, 1, now32)},
   209  		},
   210  		{
   211  			"highestMax(metric1,1)",
   212  			map[parser.MetricRequest][]*types.MetricData{
   213  				{Metric: "metric1", From: 0, Until: 1}: {
   214  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
   215  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   216  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   217  				},
   218  			},
   219  			[]*types.MetricData{types.MakeMetricData("metricA", // NOTE(dgryski): not sure if this matches graphite
   220  				[]float64{1, 1, 3, 3, 12, 11}, 1, now32)},
   221  		},
   222  		{
   223  			"highestMin(metric1,1)",
   224  			map[parser.MetricRequest][]*types.MetricData{
   225  				{Metric: "metric1", From: 0, Until: 1}: {
   226  					types.MakeMetricData("metricA", []float64{6, 1, 3, 3, 4, 12}, 1, now32),
   227  					types.MakeMetricData("metricB", []float64{2, 5, 5, 5, 5, 5}, 1, now32),
   228  					types.MakeMetricData("metricC", []float64{3, 1, 3, 3, 4, 10}, 1, now32),
   229  				},
   230  			},
   231  			[]*types.MetricData{types.MakeMetricData("metricB", // NOTE(dgryski): not sure if this matches graphite
   232  				[]float64{2, 5, 5, 5, 5, 5}, 1, now32)},
   233  		},
   234  		{
   235  			"highestCurrent(metric1,0)",
   236  			map[parser.MetricRequest][]*types.MetricData{
   237  				parser.MetricRequest{Metric: "metric1", From: 0, Until: 1}: {
   238  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   239  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   240  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   241  				},
   242  			},
   243  			[]*types.MetricData{},
   244  		},
   245  		{
   246  			"highest(metric1,\"max\")",
   247  			map[parser.MetricRequest][]*types.MetricData{
   248  				{Metric: "metric1", From: 0, Until: 1}: {
   249  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
   250  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   251  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   252  				},
   253  			},
   254  			[]*types.MetricData{types.MakeMetricData("metricA",
   255  				[]float64{1, 1, 3, 3, 12, 11}, 1, now32)},
   256  		},
   257  		{
   258  			"highest(metric1, 0, \"max\")",
   259  			map[parser.MetricRequest][]*types.MetricData{
   260  				{Metric: "metric1", From: 0, Until: 1}: {
   261  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
   262  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   263  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   264  				},
   265  			},
   266  			[]*types.MetricData{},
   267  		},
   268  		{
   269  			"highest(metric1, -1, \"max\")",
   270  			map[parser.MetricRequest][]*types.MetricData{
   271  				{Metric: "metric1", From: 0, Until: 1}: {
   272  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
   273  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   274  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   275  				},
   276  			},
   277  			[]*types.MetricData{},
   278  		},
   279  		{
   280  			"lowest(metric1,\"max\")",
   281  			map[parser.MetricRequest][]*types.MetricData{
   282  				{Metric: "metric1", From: 0, Until: 1}: {
   283  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 12, 11}, 1, now32),
   284  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   285  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 10}, 1, now32),
   286  				},
   287  			},
   288  			[]*types.MetricData{
   289  				types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   290  			},
   291  		},
   292  		{
   293  			"lowestCurrent(metric1,1)",
   294  			map[parser.MetricRequest][]*types.MetricData{
   295  				{Metric: "metric1", From: 0, Until: 1}: {
   296  					types.MakeMetricData("metricA", []float64{1, 1, 3, 3, 4, 12}, 1, now32),
   297  					types.MakeMetricData("metricB", []float64{1, 1, 3, 3, 4, 1}, 1, now32),
   298  					types.MakeMetricData("metricC", []float64{1, 1, 3, 3, 4, 15}, 1, now32),
   299  				},
   300  			},
   301  			[]*types.MetricData{types.MakeMetricData("metricB", // NOTE(dgryski): not sure if this matches graphite
   302  				[]float64{1, 1, 3, 3, 4, 1}, 1, now32)},
   303  		},
   304  	}
   305  
   306  	for _, tt := range tests {
   307  		testName := tt.Target
   308  		t.Run(testName, func(t *testing.T) {
   309  			eval := th.EvaluatorFromFunc(md[0].F)
   310  			th.TestEvalExpr(t, eval, &tt)
   311  		})
   312  	}
   313  }