package queryBuilder import ( "math" "testing" v3 "go.signoz.io/signoz/pkg/query-service/model/v3" ) func TestFuncCutOffMin(t *testing.T) { type args struct { result *v3.Result threshold float64 } tests := []struct { name string args args want *v3.Result }{ { name: "test funcCutOffMin", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.4, }, { Value: 0.3, }, { Value: 0.2, }, { Value: 0.1, }, }, }, }, }, threshold: 0.3, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.4, }, { Value: 0.3, }, { Value: math.NaN(), }, { Value: math.NaN(), }, }, }, }, }, }, { name: "test funcCutOffMin with threshold 0", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.4, }, { Value: 0.3, }, { Value: 0.2, }, { Value: 0.1, }, }, }, }, }, threshold: 0, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.4, }, { Value: 0.3, }, { Value: 0.2, }, { Value: 0.1, }, }, }, }, }, }, } for _, tt := range tests { newResult := funcCutOffMin(tt.args.result, tt.args.threshold) for j, series := range newResult.Series { for k, point := range series.Points { if math.IsNaN(tt.want.Series[j].Points[k].Value) { if !math.IsNaN(point.Value) { t.Errorf("funcCutOffMin() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } continue } if point.Value != tt.want.Series[j].Points[k].Value { t.Errorf("funcCutOffMin() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } } } } } func TestFuncCutOffMax(t *testing.T) { type args struct { result *v3.Result threshold float64 } tests := []struct { name string args args want *v3.Result }{ { name: "test funcCutOffMax", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.4, }, { Value: 0.3, }, { Value: 0.2, }, { Value: 0.1, }, }, }, }, }, threshold: 0.3, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: math.NaN(), }, { Value: math.NaN(), }, { Value: 0.3, }, { Value: 0.2, }, { Value: 0.1, }, }, }, }, }, }, { name: "test funcCutOffMax with threshold 0", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.4, }, { Value: 0.3, }, { Value: 0.2, }, { Value: 0.1, }, }, }, }, }, threshold: 0, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: math.NaN(), }, { Value: math.NaN(), }, { Value: math.NaN(), }, { Value: math.NaN(), }, { Value: math.NaN(), }, }, }, }, }, }, } for _, tt := range tests { newResult := funcCutOffMax(tt.args.result, tt.args.threshold) for j, series := range newResult.Series { for k, point := range series.Points { if math.IsNaN(tt.want.Series[j].Points[k].Value) { if !math.IsNaN(point.Value) { t.Errorf("funcCutOffMax() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } continue } if point.Value != tt.want.Series[j].Points[k].Value { t.Errorf("funcCutOffMax() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } } } } } func TestCutOffMinCumSum(t *testing.T) { type args struct { result *v3.Result threshold float64 } tests := []struct { name string args args want *v3.Result }{ { name: "test funcCutOffMin followed by funcCumulativeSum", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.2, }, { Value: 0.1, }, { Value: 0.4, }, { Value: 0.3, }, }, }, }, }, threshold: 0.3, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{ { Value: 0.5, }, { Value: 0.5, }, { Value: 0.5, }, { Value: 0.9, }, { Value: 1.2, }, }, }, }, }, }, } for _, tt := range tests { newResult := funcCutOffMin(tt.args.result, tt.args.threshold) newResult = funcCumSum(newResult) for j, series := range newResult.Series { for k, point := range series.Points { if math.IsNaN(tt.want.Series[j].Points[k].Value) { if !math.IsNaN(point.Value) { t.Errorf("funcCutOffMin() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } continue } if point.Value != tt.want.Series[j].Points[k].Value { t.Errorf("funcCutOffMin() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } } } } } func TestFuncMedian3(t *testing.T) { type args struct { result *v3.Result } tests := []struct { name string args args want *v3.Result }{ { name: "Values", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 5}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: 8}, {Timestamp: 4, Value: 2}, {Timestamp: 5, Value: 7}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 5}, {Timestamp: 2, Value: 5}, {Timestamp: 3, Value: 3}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 7}}, }, }, }, }, { name: "NaNHandling", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: math.NaN()}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: math.NaN()}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 9}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: math.NaN()}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: 5}, {Timestamp: 4, Value: 8}, {Timestamp: 5, Value: 9}}, }, }, }, }, { name: "UniformValues", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 7}, {Timestamp: 2, Value: 7}, {Timestamp: 3, Value: 7}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 7}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 7}, {Timestamp: 2, Value: 7}, {Timestamp: 3, Value: 7}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 7}}, }, }, }, }, { name: "SingleValueSeries", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 9}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 9}}, }, }, }, }, { name: "EmptySeries", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{}, }, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := funcMedian3(tt.args.result) for j, series := range got.Series { for k, point := range series.Points { if point.Value != tt.want.Series[j].Points[k].Value && !math.IsNaN(tt.want.Series[j].Points[k].Value) { t.Errorf("funcMedian3() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } } } }) } } func TestFuncMedian5(t *testing.T) { type args struct { result *v3.Result } tests := []struct { name string args args want *v3.Result }{ { name: "Values", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 5}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: 8}, {Timestamp: 4, Value: 2}, {Timestamp: 5, Value: 7}, {Timestamp: 6, Value: 9}, {Timestamp: 7, Value: 1}, {Timestamp: 8, Value: 4}, {Timestamp: 9, Value: 6}, {Timestamp: 10, Value: 10}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 5}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: 5}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 7}, {Timestamp: 6, Value: 4}, {Timestamp: 7, Value: 6}, {Timestamp: 8, Value: 6}, {Timestamp: 9, Value: 6}, {Timestamp: 10, Value: 10}}, }, }, }, }, { name: "NaNHandling", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: math.NaN()}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: math.NaN()}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 9}, {Timestamp: 6, Value: 1}, {Timestamp: 7, Value: 4}, {Timestamp: 8, Value: 6}, {Timestamp: 9, Value: 10}, {Timestamp: 10, Value: 2}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: math.NaN()}, {Timestamp: 2, Value: 3}, {Timestamp: 3, Value: 7}, {Timestamp: 4, Value: 5}, {Timestamp: 5, Value: 5.5}, {Timestamp: 6, Value: 6}, {Timestamp: 7, Value: 6}, {Timestamp: 8, Value: 4}, {Timestamp: 9, Value: 10}, {Timestamp: 10, Value: 2}}, }, }, }, }, { name: "UniformValues", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 7}, {Timestamp: 2, Value: 7}, {Timestamp: 3, Value: 7}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 7}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 7}, {Timestamp: 2, Value: 7}, {Timestamp: 3, Value: 7}, {Timestamp: 4, Value: 7}, {Timestamp: 5, Value: 7}}, }, }, }, }, { name: "SingleValueSeries", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 9}}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{{Timestamp: 1, Value: 9}}, }, }, }, }, { name: "EmptySeries", args: args{ result: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{}, }, }, }, }, want: &v3.Result{ Series: []*v3.Series{ { Points: []v3.Point{}, }, }, }, }, } for _, tt := range tests { got := funcMedian5(tt.args.result) for j, series := range got.Series { for k, point := range series.Points { if point.Value != tt.want.Series[j].Points[k].Value && !math.IsNaN(tt.want.Series[j].Points[k].Value) { t.Errorf("funcMedian5() = %v, want %v", point.Value, tt.want.Series[j].Points[k].Value) } } } } }