github.com/go-graphite/carbonapi@v0.17.0/expr/functions/divideSeries/function_test.go (about) 1 package divideSeries 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 TestDivideSeriesMultiReturn(t *testing.T) { 26 now32 := time.Now().Unix() 27 28 tests := []th.MultiReturnEvalTestItem{ 29 { 30 "divideSeries(metric[12],metric2)", 31 map[parser.MetricRequest][]*types.MetricData{ 32 {Metric: "metric[12]", From: 0, Until: 1}: { 33 types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32), 34 types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32), 35 }, 36 {Metric: "metric1", From: 0, Until: 1}: { 37 types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5}, 1, now32), 38 }, 39 {Metric: "metric2", From: 0, Until: 1}: { 40 types.MakeMetricData("metric2", []float64{2, 4, 6, 8, 10}, 1, now32), 41 }, 42 }, 43 "divideSeries", 44 map[string][]*types.MetricData{ 45 "divideSeries(metric1,metric2)": {types.MakeMetricData("divideSeries(metric1,metric2)", []float64{0.5, 0.5, 0.5, 0.5, 0.5}, 1, now32)}, 46 "divideSeries(metric2,metric2)": {types.MakeMetricData("divideSeries(metric2,metric2)", []float64{1, 1, 1, 1, 1}, 1, now32)}, 47 }, 48 }, 49 } 50 51 for _, tt := range tests { 52 testName := tt.Target 53 t.Run(testName, func(t *testing.T) { 54 eval := th.EvaluatorFromFunc(md[0].F) 55 th.TestMultiReturnEvalExpr(t, eval, &tt) 56 }) 57 } 58 } 59 60 func TestDivideSeries(t *testing.T) { 61 now32 := time.Now().Unix() 62 63 tests := []th.EvalTestItem{ 64 { 65 "divideSeries(metric1,metric2)", 66 map[parser.MetricRequest][]*types.MetricData{ 67 {Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", []float64{1, math.NaN(), math.NaN(), 3, 4, 12}, 1, now32)}, 68 {Metric: "metric2", From: 0, Until: 1}: {types.MakeMetricData("metric2", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 1, now32)}, 69 }, 70 []*types.MetricData{types.MakeMetricData("divideSeries(metric1,metric2)", 71 []float64{0.5, math.NaN(), math.NaN(), math.NaN(), math.NaN(), 2}, 1, now32)}, 72 }, 73 { 74 "divideSeries(metric[12])", 75 map[parser.MetricRequest][]*types.MetricData{ 76 {Metric: "metric[12]", From: 0, Until: 1}: { 77 types.MakeMetricData("metric1", []float64{1, math.NaN(), math.NaN(), 3, 4, 12}, 1, now32), 78 types.MakeMetricData("metric2", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 1, now32), 79 }, 80 }, 81 []*types.MetricData{types.MakeMetricData("divideSeries(metric[12])", 82 []float64{0.5, math.NaN(), math.NaN(), math.NaN(), math.NaN(), 2}, 1, now32).SetNameTag("metric1")}, 83 }, 84 { 85 "divideSeries(testMetric,metric)", // verify that a non-existant denominator will not error out and instead will return a list of math.NaN() values 86 map[parser.MetricRequest][]*types.MetricData{ 87 {Metric: "testMetric", From: 0, Until: 1}: {types.MakeMetricData("testMetric", []float64{1, math.NaN(), math.NaN(), 3, 4, 12}, 1, now32)}, 88 }, 89 []*types.MetricData{types.MakeMetricData("divideSeries(testMetric,MISSING)", 90 []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN()}, 1, now32)}, 91 }, 92 } 93 94 for _, tt := range tests { 95 testName := tt.Target 96 t.Run(testName, func(t *testing.T) { 97 eval := th.EvaluatorFromFunc(md[0].F) 98 th.TestEvalExpr(t, eval, &tt) 99 }) 100 } 101 } 102 103 func TestDivideSeriesAligned(t *testing.T) { 104 startTime := int64(0) 105 106 tests := []th.EvalTestItemWithRange{ 107 { 108 "divideSeries(metric1,metric2)", 109 map[parser.MetricRequest][]*types.MetricData{ 110 {Metric: "metric1", From: 0, Until: 1}: { 111 types.MakeMetricData("metric1", []float64{1, math.NaN(), math.NaN(), 3, 4, 12, 2}, 1, startTime), 112 }, 113 {Metric: "metric2", From: 0, Until: 1}: { 114 types.MakeMetricData("metric2", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 1, startTime), 115 }, 116 }, 117 []*types.MetricData{types.MakeMetricData("divideSeries(metric1,metric2)", 118 []float64{0.5, math.NaN(), math.NaN(), math.NaN(), math.NaN(), 2, math.NaN()}, 1, startTime)}, 119 startTime, 120 startTime + 1, 121 }, 122 { 123 "divideSeries(metric[23])", 124 map[parser.MetricRequest][]*types.MetricData{ 125 {Metric: "metric[23]", From: 0, Until: 1}: { 126 types.MakeMetricData("metric2", []float64{1, math.NaN(), math.NaN(), 3, 4, 12, 2}, 1, startTime), 127 types.MakeMetricData("metric3", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 1, startTime), 128 }, 129 }, 130 []*types.MetricData{types.MakeMetricData("divideSeries(metric[23])", 131 []float64{0.5, math.NaN(), math.NaN(), math.NaN(), math.NaN(), 2, math.NaN()}, 1, startTime).SetNameTag("metric2")}, 132 startTime, 133 startTime + 1, 134 }, 135 { 136 "divideSeries(metric3,metric4)", 137 map[parser.MetricRequest][]*types.MetricData{ 138 {Metric: "metric3", From: 0, Until: 1}: { 139 types.MakeMetricData("metric3", []float64{1, math.NaN(), math.NaN(), 3, 4, 8, 2, math.NaN(), 3, math.NaN(), 0, 6}, 5, startTime), 140 }, 141 {Metric: "metric4", From: 0, Until: 1}: { 142 types.MakeMetricData("metric4", []float64{2, math.NaN(), 3, math.NaN(), 0, 6}, 10, startTime), 143 }, 144 }, 145 []*types.MetricData{types.MakeMetricData("divideSeries(metric3,metric4)", 146 []float64{0.5, math.NaN(), 2, math.NaN(), math.NaN(), 0.5}, 10, startTime)}, 147 startTime, 148 startTime + 1, 149 }, 150 } 151 152 for _, tt := range tests { 153 t.Run(tt.Target, func(t *testing.T) { 154 eval := th.EvaluatorFromFunc(md[0].F) 155 th.TestEvalExprWithRange(t, eval, &tt) 156 }) 157 } 158 }