1package mathexp
2
3import (
4	"testing"
5	"time"
6
7	"github.com/grafana/grafana-plugin-sdk-go/backend"
8	"github.com/stretchr/testify/assert"
9	"github.com/stretchr/testify/require"
10)
11
12func TestResampleSeries(t *testing.T) {
13	var tests = []struct {
14		name             string
15		interval         time.Duration
16		downsampler      string
17		upsampler        string
18		timeRange        backend.TimeRange
19		seriesToResample Series
20		series           Series
21	}{
22		{
23			name:        "resample series: time range shorter than the rule interval",
24			interval:    time.Second * 5,
25			downsampler: "mean",
26			upsampler:   "fillna",
27			timeRange: backend.TimeRange{
28				From: time.Unix(0, 0),
29				To:   time.Unix(4, 0),
30			},
31			seriesToResample: makeSeries("", nil, tp{
32				time.Unix(2, 0), float64Pointer(2),
33			}, tp{
34				time.Unix(7, 0), float64Pointer(1),
35			}),
36		},
37		{
38			name:        "resample series: invalid time range",
39			interval:    time.Second * 5,
40			downsampler: "mean",
41			upsampler:   "fillna",
42			timeRange: backend.TimeRange{
43				From: time.Unix(11, 0),
44				To:   time.Unix(0, 0),
45			},
46			seriesToResample: makeSeries("", nil, tp{
47				time.Unix(2, 0), float64Pointer(2),
48			}, tp{
49				time.Unix(7, 0), float64Pointer(1),
50			}),
51		},
52		{
53			name:        "resample series: downsampling (mean / pad)",
54			interval:    time.Second * 5,
55			downsampler: "mean",
56			upsampler:   "pad",
57			timeRange: backend.TimeRange{
58				From: time.Unix(0, 0),
59				To:   time.Unix(16, 0),
60			},
61			seriesToResample: makeSeries("", nil, tp{
62				time.Unix(2, 0), float64Pointer(2),
63			}, tp{
64				time.Unix(4, 0), float64Pointer(3),
65			}, tp{
66				time.Unix(7, 0), float64Pointer(1),
67			}, tp{
68				time.Unix(9, 0), float64Pointer(2),
69			}),
70			series: makeSeries("", nil, tp{
71				time.Unix(0, 0), nil,
72			}, tp{
73				time.Unix(5, 0), float64Pointer(2.5),
74			}, tp{
75				time.Unix(10, 0), float64Pointer(1.5),
76			}, tp{
77				time.Unix(15, 0), float64Pointer(2),
78			}),
79		},
80		{
81			name:        "resample series: downsampling (max / fillna)",
82			interval:    time.Second * 5,
83			downsampler: "max",
84			upsampler:   "fillna",
85			timeRange: backend.TimeRange{
86				From: time.Unix(0, 0),
87				To:   time.Unix(16, 0),
88			},
89			seriesToResample: makeSeries("", nil, tp{
90				time.Unix(2, 0), float64Pointer(2),
91			}, tp{
92				time.Unix(4, 0), float64Pointer(3),
93			}, tp{
94				time.Unix(7, 0), float64Pointer(1),
95			}, tp{
96				time.Unix(9, 0), float64Pointer(2),
97			}),
98			series: makeSeries("", nil, tp{
99				time.Unix(0, 0), nil,
100			}, tp{
101				time.Unix(5, 0), float64Pointer(3),
102			}, tp{
103				time.Unix(10, 0), float64Pointer(2),
104			}, tp{
105				time.Unix(15, 0), nil,
106			}),
107		},
108		{
109			name:        "resample series: downsampling (min / fillna)",
110			interval:    time.Second * 5,
111			downsampler: "min",
112			upsampler:   "fillna",
113			timeRange: backend.TimeRange{
114				From: time.Unix(0, 0),
115				To:   time.Unix(16, 0),
116			},
117			seriesToResample: makeSeries("", nil, tp{
118				time.Unix(2, 0), float64Pointer(2),
119			}, tp{
120				time.Unix(4, 0), float64Pointer(3),
121			}, tp{
122				time.Unix(7, 0), float64Pointer(1),
123			}, tp{
124				time.Unix(9, 0), float64Pointer(2),
125			}),
126			series: makeSeries("", nil, tp{
127				time.Unix(0, 0), nil,
128			}, tp{
129				time.Unix(5, 0), float64Pointer(2),
130			}, tp{
131				time.Unix(10, 0), float64Pointer(1),
132			}, tp{
133				time.Unix(15, 0), nil,
134			}),
135		},
136		{
137			name:        "resample series: downsampling (sum / fillna)",
138			interval:    time.Second * 5,
139			downsampler: "sum",
140			upsampler:   "fillna",
141			timeRange: backend.TimeRange{
142				From: time.Unix(0, 0),
143				To:   time.Unix(16, 0),
144			},
145			seriesToResample: makeSeries("", nil, tp{
146				time.Unix(2, 0), float64Pointer(2),
147			}, tp{
148				time.Unix(4, 0), float64Pointer(3),
149			}, tp{
150				time.Unix(7, 0), float64Pointer(1),
151			}, tp{
152				time.Unix(9, 0), float64Pointer(2),
153			}),
154			series: makeSeries("", nil, tp{
155				time.Unix(0, 0), nil,
156			}, tp{
157				time.Unix(5, 0), float64Pointer(5),
158			}, tp{
159				time.Unix(10, 0), float64Pointer(3),
160			}, tp{
161				time.Unix(15, 0), nil,
162			}),
163		},
164		{
165			name:        "resample series: downsampling (mean / fillna)",
166			interval:    time.Second * 5,
167			downsampler: "mean",
168			upsampler:   "fillna",
169			timeRange: backend.TimeRange{
170				From: time.Unix(0, 0),
171				To:   time.Unix(16, 0),
172			},
173			seriesToResample: makeSeries("", nil, tp{
174				time.Unix(2, 0), float64Pointer(2),
175			}, tp{
176				time.Unix(4, 0), float64Pointer(3),
177			}, tp{
178				time.Unix(7, 0), float64Pointer(1),
179			}, tp{
180				time.Unix(9, 0), float64Pointer(2),
181			}),
182			series: makeSeries("", nil, tp{
183				time.Unix(0, 0), nil,
184			}, tp{
185				time.Unix(5, 0), float64Pointer(2.5),
186			}, tp{
187				time.Unix(10, 0), float64Pointer(1.5),
188			}, tp{
189				time.Unix(15, 0), nil,
190			}),
191		},
192		{
193			name:        "resample series: upsampling (mean / pad )",
194			interval:    time.Second * 2,
195			downsampler: "mean",
196			upsampler:   "pad",
197			timeRange: backend.TimeRange{
198				From: time.Unix(0, 0),
199				To:   time.Unix(11, 0),
200			},
201			seriesToResample: makeSeries("", nil, tp{
202				time.Unix(2, 0), float64Pointer(2),
203			}, tp{
204				time.Unix(7, 0), float64Pointer(1),
205			}),
206			series: makeSeries("", nil, tp{
207				time.Unix(0, 0), nil,
208			}, tp{
209				time.Unix(2, 0), float64Pointer(2),
210			}, tp{
211				time.Unix(4, 0), float64Pointer(2),
212			}, tp{
213				time.Unix(6, 0), float64Pointer(2),
214			}, tp{
215				time.Unix(8, 0), float64Pointer(1),
216			}, tp{
217				time.Unix(10, 0), float64Pointer(1),
218			}),
219		},
220		{
221			name:        "resample series: upsampling (mean / backfilling )",
222			interval:    time.Second * 2,
223			downsampler: "mean",
224			upsampler:   "backfilling",
225			timeRange: backend.TimeRange{
226				From: time.Unix(0, 0),
227				To:   time.Unix(11, 0),
228			},
229			seriesToResample: makeSeries("", nil, tp{
230				time.Unix(2, 0), float64Pointer(2),
231			}, tp{
232				time.Unix(7, 0), float64Pointer(1),
233			}),
234			series: makeSeries("", nil, tp{
235				time.Unix(0, 0), float64Pointer(2),
236			}, tp{
237				time.Unix(2, 0), float64Pointer(2),
238			}, tp{
239				time.Unix(4, 0), float64Pointer(1),
240			}, tp{
241				time.Unix(6, 0), float64Pointer(1),
242			}, tp{
243				time.Unix(8, 0), float64Pointer(1),
244			}, tp{
245				time.Unix(10, 0), nil,
246			}),
247		},
248	}
249	for _, tt := range tests {
250		t.Run(tt.name, func(t *testing.T) {
251			series, err := tt.seriesToResample.Resample("", tt.interval, tt.downsampler, tt.upsampler, tt.timeRange.From, tt.timeRange.To)
252			if tt.series.Frame == nil {
253				require.Error(t, err)
254			} else {
255				require.NoError(t, err)
256				assert.Equal(t, tt.series, series)
257			}
258		})
259	}
260}
261