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

     1  package seriesList
     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 TestFunction(t *testing.T) {
    26  	now32 := int64(time.Now().Unix())
    27  
    28  	tests := []th.EvalTestItem{
    29  		{
    30  			"diffSeriesLists(metric1,metric2)",
    31  			map[parser.MetricRequest][]*types.MetricData{
    32  				{Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", []float64{1, math.NaN(), math.NaN(), 3, 4, 12}, 1, now32)},
    33  				{Metric: "metric2", From: 0, Until: 1}: {types.MakeMetricData("metric2", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 1, now32)},
    34  			},
    35  			[]*types.MetricData{types.MakeMetricData("diffSeries(metric1,metric2)",
    36  				[]float64{-1, math.NaN(), math.NaN(), math.NaN(), 4, 6}, 1, now32)},
    37  		},
    38  		{
    39  			"sumSeriesLists(metric1,metric2)",
    40  			map[parser.MetricRequest][]*types.MetricData{
    41  				{Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", []float64{1, math.NaN(), math.NaN(), 3, 4, 12}, 1, now32)},
    42  				{Metric: "metric2", From: 0, Until: 1}: {types.MakeMetricData("metric2", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 1, now32)},
    43  			},
    44  			[]*types.MetricData{types.MakeMetricData("sumSeries(metric1,metric2)",
    45  				[]float64{3, math.NaN(), math.NaN(), math.NaN(), 4, 18}, 1, now32)},
    46  		},
    47  	}
    48  
    49  	for _, tt := range tests {
    50  		testName := tt.Target
    51  		t.Run(testName, func(t *testing.T) {
    52  			eval := th.EvaluatorFromFunc(md[0].F)
    53  			th.TestEvalExpr(t, eval, &tt)
    54  		})
    55  	}
    56  }
    57  
    58  func TestSeriesListMultiReturn(t *testing.T) {
    59  	now32 := int64(time.Now().Unix())
    60  
    61  	tests := []th.MultiReturnEvalTestItem{
    62  		{
    63  			"divideSeriesLists(metric[12],metric[12])",
    64  			map[parser.MetricRequest][]*types.MetricData{
    65  				{Metric: "metric[12]", From: 0, Until: 1}: {
    66  					types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32),
    67  					types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32),
    68  				},
    69  			},
    70  			"divideSeriesListSameGroups",
    71  			map[string][]*types.MetricData{
    72  				"divideSeries(metric1,metric1)": {types.MakeMetricData("divideSeries(metric1,metric1)", []float64{1, 1, 1, 1, 1}, 1, now32)},
    73  				"divideSeries(metric2,metric2)": {types.MakeMetricData("divideSeries(metric2,metric2)", []float64{1, 1, 1, 1, 1}, 1, now32)},
    74  			},
    75  		},
    76  		{
    77  			"multiplySeriesLists(metric[12],metric[12])",
    78  			map[parser.MetricRequest][]*types.MetricData{
    79  				{Metric: "metric[12]", From: 0, Until: 1}: {
    80  					types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32),
    81  					types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32),
    82  				},
    83  			},
    84  			"multiplySeriesListSameGroups",
    85  			map[string][]*types.MetricData{
    86  				"multiplySeries(metric1,metric1)": {types.MakeMetricData("multiplySeries(metric1,metric1)", []float64{1, 4, 9, 16, 25}, 1, now32)},
    87  				"multiplySeries(metric2,metric2)": {types.MakeMetricData("multiplySeries(metric2,metric2)", []float64{4, 16, 36, 64, 100}, 1, now32)},
    88  			},
    89  		},
    90  		{
    91  			"diffSeriesLists(metric[12],metric[12])",
    92  			map[parser.MetricRequest][]*types.MetricData{
    93  				{Metric: "metric[12]", From: 0, Until: 1}: {
    94  					types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32),
    95  					types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32),
    96  				},
    97  			},
    98  			"diffSeriesListSameGroups",
    99  			map[string][]*types.MetricData{
   100  				"diffSeries(metric1,metric1)": {types.MakeMetricData("diffSeries(metric1,metric1)", []float64{0, 0, 0, 0, 0}, 1, now32)},
   101  				"diffSeries(metric2,metric2)": {types.MakeMetricData("diffSeries(metric2,metric2)", []float64{0, 0, 0, 0, 0}, 1, now32)},
   102  			},
   103  		},
   104  		{
   105  			"diffSeriesLists(metric[12],metric[134])",
   106  			map[parser.MetricRequest][]*types.MetricData{
   107  				{Metric: "metric[12]", From: 0, Until: 1}: {
   108  					types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32),
   109  					types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32),
   110  				},
   111  				{Metric: "metric[134]", From: 0, Until: 1}: {
   112  					types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32),
   113  					types.MakeMetricData("metric3", []float64{2, 4, 6, 8, 10}, 1, now32),
   114  					types.MakeMetricData("metric4", []float64{2, 4, 6, 8, 10}, 1, now32),
   115  				},
   116  			},
   117  			"diffSeriesListSameGroups",
   118  			map[string][]*types.MetricData{
   119  				"diffSeries(metric1,metric1)": {types.MakeMetricData("diffSeries(metric1,metric1)", []float64{0, 0, 0, 0, 0}, 1, now32)},
   120  			},
   121  		},
   122  		{
   123  			"sumSeriesLists(metric[12],metric[12])",
   124  			map[parser.MetricRequest][]*types.MetricData{
   125  				{Metric: "metric[12]", From: 0, Until: 1}: {
   126  					types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32),
   127  					types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32),
   128  				},
   129  			},
   130  			"sumSeriesListSameGroups",
   131  			map[string][]*types.MetricData{
   132  				"sumSeries(metric1,metric1)": {types.MakeMetricData("sumSeries(metric1,metric1)", []float64{2, 4, 6, 8, 10}, 1, now32)},
   133  				"sumSeries(metric2,metric2)": {types.MakeMetricData("sumSeries(metric2,metric2)", []float64{4, 8, 12, 16, 20}, 1, now32)},
   134  			},
   135  		},
   136  	}
   137  
   138  	for _, tt := range tests {
   139  		testName := tt.Target
   140  		t.Run(testName, func(t *testing.T) {
   141  			eval := th.EvaluatorFromFunc(md[0].F)
   142  			th.TestMultiReturnEvalExpr(t, eval, &tt)
   143  		})
   144  	}
   145  
   146  }
   147  
   148  func TestDivideSeriesMismatchedData(t *testing.T) {
   149  	var startTime int64 = 0
   150  
   151  	tests := []th.EvalTestItemWithRange{
   152  		{
   153  			Target: `divideSeriesLists(metric1,metric2)`, // Test different step values for metrics
   154  			M: map[parser.MetricRequest][]*types.MetricData{
   155  				{Metric: "metric1", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, startTime)},
   156  				{Metric: "metric2", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metric2", []float64{1, 2, 3, 4, 5}, 2, startTime)},
   157  			},
   158  			Want: []*types.MetricData{types.MakeMetricData("divideSeries(metric1,metric2)",
   159  				[]float64{1.5, 1.75, 1.6666666666666667, math.NaN(), math.NaN()}, 2, startTime)},
   160  			From:  startTime,
   161  			Until: startTime + 1,
   162  		},
   163  		{
   164  			Target: `divideSeriesLists(metricA,metricB)`, // Test different step values for metrics
   165  			M: map[parser.MetricRequest][]*types.MetricData{
   166  				{Metric: "metricA", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metricA", []float64{1, 2, 3, 4, 5}, 10, startTime)},
   167  				{Metric: "metricB", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metricB", []float64{1, 2, 3, 4, 5}, 5, startTime)},
   168  			},
   169  			Want: []*types.MetricData{types.MakeMetricData("divideSeries(metricA,metricB)",
   170  				[]float64{0.6666666666666666, 0.5714285714285714, 0.6, math.NaN(), math.NaN()}, 10, startTime)},
   171  			From:  startTime,
   172  			Until: startTime + 1,
   173  		},
   174  		{
   175  			Target: `divideSeriesLists(metricC,metricD)`, // Test different number of values for metrics
   176  			M: map[parser.MetricRequest][]*types.MetricData{
   177  				{Metric: "metricC", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metricC", []float64{1, 2, 3, 4}, 1, startTime)},
   178  				{Metric: "metricD", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metricD", []float64{1, 2, 3, 4, 5}, 1, startTime)},
   179  			},
   180  			Want: []*types.MetricData{types.MakeMetricData("divideSeries(metricC,metricD)",
   181  				[]float64{1, 1, 1, 1, math.NaN()}, 1, startTime)},
   182  			From:  startTime,
   183  			Until: startTime + 1,
   184  		},
   185  		{
   186  			Target: `divideSeriesLists(metricE,metricF)`, // Test different number of values and steps in metrics
   187  			M: map[parser.MetricRequest][]*types.MetricData{
   188  				{Metric: "metricE", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metricE", []float64{1, 2, 3, 4, 5}, 2, startTime)},
   189  				{Metric: "metricF", From: startTime, Until: startTime + 1}: {types.MakeMetricData("metricF", []float64{1, 2, 3, 4}, 1, startTime)},
   190  			},
   191  			Want: []*types.MetricData{types.MakeMetricData("divideSeries(metricE,metricF)",
   192  				[]float64{0.6666666666666666, 0.5714285714285714, math.NaN(), math.NaN(), math.NaN()}, 2, startTime)},
   193  			From:  startTime,
   194  			Until: startTime + 1,
   195  		},
   196  	}
   197  
   198  	for _, tt := range tests {
   199  		testName := tt.Target
   200  		t.Run(testName, func(t *testing.T) {
   201  			eval := th.EvaluatorFromFunc(md[0].F)
   202  			th.TestEvalExprWithRange(t, eval, &tt)
   203  		})
   204  	}
   205  }