View Javadoc
1   package de.dlr.shepard.data.timeseries.services;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
5   import static org.mockito.Mockito.when;
6   
7   import de.dlr.shepard.auth.security.AuthenticationContext;
8   import de.dlr.shepard.auth.users.entities.User;
9   import de.dlr.shepard.auth.users.services.UserService;
10  import de.dlr.shepard.common.exceptions.InvalidRequestException;
11  import de.dlr.shepard.data.timeseries.TimeseriesTestDataGenerator;
12  import de.dlr.shepard.data.timeseries.io.TimeseriesContainerIO;
13  import de.dlr.shepard.data.timeseries.model.TimeseriesDataPoint;
14  import de.dlr.shepard.data.timeseries.model.TimeseriesDataPointsQueryParams;
15  import de.dlr.shepard.data.timeseries.model.enums.AggregateFunction;
16  import de.dlr.shepard.data.timeseries.model.enums.FillOption;
17  import io.quarkus.test.InjectMock;
18  import io.quarkus.test.junit.QuarkusTest;
19  import jakarta.inject.Inject;
20  import jakarta.transaction.Transactional;
21  import java.math.BigDecimal;
22  import java.time.Duration;
23  import java.util.ArrayList;
24  import java.util.List;
25  import org.junit.jupiter.api.Test;
26  
27  @QuarkusTest
28  public class TimeseriesServiceAggregationTest {
29  
30    @InjectMock
31    UserService userService;
32  
33    @InjectMock
34    AuthenticationContext authenticationContext;
35  
36    @Inject
37    TimeseriesService timeseriesService;
38  
39    @Inject
40    TimeseriesContainerService timeseriesContainerService;
41  
42    private final String containerName = "AnotherContainer";
43    private final double doubleEpsilon = 1E-9;
44  
45    @Test
46    @Transactional
47    public void getDataPointsByTimeseries_getMax_returnMax_noFill_noGroupBy() {
48      User user = new User("Testuser");
49      TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
50      containerIO.setName(containerName);
51  
52      when(userService.getCurrentUser()).thenReturn(user);
53      when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
54  
55      var container = timeseriesContainerService.createContainer(containerIO);
56      var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
57      InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
58      List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
59        List.of(
60          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
61          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
62          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
63        )
64      );
65  
66      this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
67      TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
68        InstantHelper.fromGermanDate("01.01.2024").toNano(),
69        instantHelper.addSeconds(1).toNano(),
70        null,
71        null,
72        AggregateFunction.MAX
73      );
74      var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
75  
76      assertEquals(1, actual.size());
77      assertEquals(22.3, (Double) actual.get(0).getValue(), doubleEpsilon);
78    }
79  
80    @Test
81    @Transactional
82    public void getDataPointsByTimeseries_getMean_returnMean_noFill_noGroupBy() {
83      User user = new User("Testuser");
84      TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
85      containerIO.setName(containerName);
86  
87      when(userService.getCurrentUser()).thenReturn(user);
88      when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
89  
90      var container = timeseriesContainerService.createContainer(containerIO);
91      var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
92      InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
93      List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
94        List.of(
95          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
96          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
97          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
98        )
99      );
100 
101     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
102     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
103       InstantHelper.fromGermanDate("01.01.2024").toNano(),
104       InstantHelper.fromGermanDate("01.01.2024").addSeconds(3).toNano(),
105       null,
106       null,
107       AggregateFunction.MEAN
108     );
109     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
110 
111     assertEquals(1, actual.size());
112     assertEquals(22.2, (Double) actual.get(0).getValue(), doubleEpsilon);
113   }
114 
115   @Test
116   @Transactional
117   public void getDataPointsByTimeseries_getMin_returnMin_noFill_noGroupBy() {
118     User user = new User("Testuser");
119     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
120     containerIO.setName(containerName);
121 
122     when(userService.getCurrentUser()).thenReturn(user);
123     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
124 
125     var container = timeseriesContainerService.createContainer(containerIO);
126     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
127     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
128     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
129       List.of(
130         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
131         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
132         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
133       )
134     );
135 
136     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
137     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
138       InstantHelper.fromGermanDate("01.01.2024").toNano(),
139       InstantHelper.fromGermanDate("01.01.2024").addSeconds(3).toNano(),
140       null,
141       null,
142       AggregateFunction.MIN
143     );
144     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
145 
146     assertEquals(1, actual.size());
147     assertEquals(22.1, (Double) actual.get(0).getValue(), doubleEpsilon);
148   }
149 
150   @Test
151   @Transactional
152   public void getDataPointsByTimeseries_getLast_returnLast_noFill_noGroupBy() {
153     User user = new User("Testuser");
154     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
155     containerIO.setName(containerName);
156 
157     when(userService.getCurrentUser()).thenReturn(user);
158     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
159 
160     var container = timeseriesContainerService.createContainer(containerIO);
161     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
162     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
163     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
164       List.of(
165         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
166         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
167         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
168       )
169     );
170 
171     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
172     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
173       InstantHelper.fromGermanDate("01.01.2024").toNano(),
174       InstantHelper.fromGermanDate("01.01.2024").addSeconds(3).toNano(),
175       null,
176       null,
177       AggregateFunction.LAST
178     );
179     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
180 
181     assertEquals(1, actual.size());
182     assertEquals(22.2, (Double) actual.get(0).getValue(), doubleEpsilon);
183   }
184 
185   @Test
186   @Transactional
187   public void getDataPointsByTimeseries_getFirst_returnFirst_noFill_noGroupBy() {
188     User user = new User("Testuser");
189     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
190     containerIO.setName(containerName);
191 
192     when(userService.getCurrentUser()).thenReturn(user);
193     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
194 
195     var container = timeseriesContainerService.createContainer(containerIO);
196     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
197     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
198     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
199       List.of(
200         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
201         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
202         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
203       )
204     );
205 
206     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
207     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
208       InstantHelper.fromGermanDate("01.01.2024").toNano(),
209       InstantHelper.fromGermanDate("01.01.2024").addSeconds(3).toNano(),
210       null,
211       null,
212       AggregateFunction.FIRST
213     );
214     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
215 
216     assertEquals(1, actual.size());
217     assertEquals(22.1, (Double) actual.get(0).getValue(), doubleEpsilon);
218   }
219 
220   @Test
221   @Transactional
222   public void getDataPointsByTimeseries_getSpread_returnSpread_noFill_noGroupBy() {
223     User user = new User("Testuser");
224     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
225     containerIO.setName(containerName);
226 
227     when(userService.getCurrentUser()).thenReturn(user);
228     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
229 
230     var container = timeseriesContainerService.createContainer(containerIO);
231     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
232     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
233     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
234       List.of(
235         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
236         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
237         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
238       )
239     );
240 
241     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
242     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
243       InstantHelper.fromGermanDate("01.01.2024").toNano(),
244       InstantHelper.fromGermanDate("01.01.2024").addSeconds(3).toNano(),
245       null,
246       null,
247       AggregateFunction.SPREAD
248     );
249     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
250 
251     assertEquals(1, actual.size());
252     assertEquals(0.2, (Double) actual.get(0).getValue(), doubleEpsilon);
253   }
254 
255   @Test
256   @Transactional
257   public void getDataPointsByTimeseries_getMode_returnMode_noFill_noGroupBy() {
258     User user = new User("Testuser");
259     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
260     containerIO.setName(containerName);
261 
262     when(userService.getCurrentUser()).thenReturn(user);
263     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
264 
265     var container = timeseriesContainerService.createContainer(containerIO);
266     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
267     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
268     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
269       List.of(
270         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
271         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.1),
272         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
273         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
274         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
275         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
276         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.4),
277         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2),
278         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2),
279         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
280       )
281     );
282 
283     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
284     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
285       InstantHelper.fromGermanDate("01.01.2024").toNano(),
286       instantHelper.addSeconds(1).toNano(),
287       null,
288       null,
289       AggregateFunction.MODE
290     );
291     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
292 
293     assertEquals(1, actual.size());
294     assertEquals(22.3, (Double) actual.get(0).getValue(), doubleEpsilon);
295   }
296 
297   @Test
298   @Transactional
299   public void getDataPointsByTimeseries_getMedian_returnMedian_noFill_noGroupBy() {
300     User user = new User("Testuser");
301     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
302     containerIO.setName(containerName);
303 
304     when(userService.getCurrentUser()).thenReturn(user);
305     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
306 
307     var container = timeseriesContainerService.createContainer(containerIO);
308     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
309     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
310     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
311       List.of(
312         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 2.0),
313         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 3.0),
314         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 11.0),
315         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 13.0),
316         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 26.0),
317         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 34.0),
318         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 47.0)
319       )
320     );
321 
322     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
323     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
324       InstantHelper.fromGermanDate("01.01.2024").toNano(),
325       InstantHelper.fromGermanDate("01.01.2024").addSeconds(8).toNano(),
326       null,
327       null,
328       AggregateFunction.MEDIAN
329     );
330     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
331 
332     assertEquals(1, actual.size());
333     assertEquals(13.0, (Double) actual.get(0).getValue(), doubleEpsilon);
334   }
335 
336   @Test
337   @Transactional
338   public void getDataPointsByTimeseries_getCount_returnCount_noFill_noGroupBy() {
339     User user = new User("Testuser");
340     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
341     containerIO.setName(containerName);
342 
343     when(userService.getCurrentUser()).thenReturn(user);
344     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
345 
346     var container = timeseriesContainerService.createContainer(containerIO);
347     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
348     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
349     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
350       List.of(
351         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 2.0),
352         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 3.0),
353         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 11.0),
354         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 13.0),
355         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 26.0),
356         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 34.0),
357         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 47.0)
358       )
359     );
360 
361     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
362     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
363       InstantHelper.fromGermanDate("01.01.2024").toNano(),
364       instantHelper.addSeconds(2).toNano(),
365       null,
366       null,
367       AggregateFunction.COUNT
368     );
369     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
370 
371     assertEquals(1, actual.size());
372     assertEquals((long) 7, actual.get(0).getValue());
373   }
374 
375   @Test
376   @Transactional
377   public void getDataPointsByTimeseries_getSum_returnSum_noFill_noGroupBy() {
378     User user = new User("Testuser");
379     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
380     containerIO.setName(containerName);
381 
382     when(userService.getCurrentUser()).thenReturn(user);
383     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
384 
385     var container = timeseriesContainerService.createContainer(containerIO);
386     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
387     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
388     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
389       List.of(
390         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 2.0),
391         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 3.0),
392         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 5.0),
393         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 7.0)
394       )
395     );
396 
397     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
398     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
399       InstantHelper.fromGermanDate("01.01.2024").toNano(),
400       instantHelper.addSeconds(2).toNano(),
401       null,
402       null,
403       AggregateFunction.SUM
404     );
405     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
406 
407     assertEquals(1, actual.size());
408     assertEquals(17.0, (Double) actual.get(0).getValue(), doubleEpsilon);
409   }
410 
411   @Test
412   @Transactional
413   public void getDataPointsByTimeseries_getStddev_returnStddev_noFill_noGroupBy() {
414     User user = new User("Testuser");
415     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
416     containerIO.setName(containerName);
417 
418     when(userService.getCurrentUser()).thenReturn(user);
419     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
420 
421     var container = timeseriesContainerService.createContainer(containerIO);
422     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
423     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
424     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
425       List.of(
426         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 10.0),
427         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 12.0),
428         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 23.0),
429         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 23.0),
430         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 16.0),
431         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 23.0),
432         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 21.0),
433         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 16.0)
434       )
435     );
436 
437     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
438     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
439       InstantHelper.fromGermanDate("01.01.2024").toNano(),
440       instantHelper.addSeconds(2).toNano(),
441       null,
442       null,
443       AggregateFunction.STDDEV
444     );
445     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
446 
447     assertEquals(1, actual.size());
448     assertEquals(5.2372293656638, (Double) actual.get(0).getValue(), doubleEpsilon);
449   }
450 
451   @Test
452   @Transactional
453   public void getDataPointsByTimeseries_getSum_returnSum_noFill_noGroupBy_integer() {
454     User user = new User("Testuser");
455     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
456     containerIO.setName(containerName);
457 
458     when(userService.getCurrentUser()).thenReturn(user);
459     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
460 
461     var container = timeseriesContainerService.createContainer(containerIO);
462     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
463     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
464     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
465       List.of(
466         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.toNano(), 2),
467         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 3),
468         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 5),
469         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 7)
470       )
471     );
472 
473     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
474     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
475       InstantHelper.fromGermanDate("01.01.2024").toNano(),
476       instantHelper.addSeconds(2).toNano(),
477       null,
478       null,
479       AggregateFunction.SUM
480     );
481     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
482 
483     assertEquals(1, actual.size());
484     assertEquals(BigDecimal.valueOf(17), actual.get(0).getValue());
485   }
486 
487   @Test
488   @Transactional
489   public void getDataPointsByTimeseries_getStddev_returnStddev_noFill_noGroupBy_integer() {
490     User user = new User("Testuser");
491     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
492     containerIO.setName(containerName);
493 
494     when(userService.getCurrentUser()).thenReturn(user);
495     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
496 
497     var container = timeseriesContainerService.createContainer(containerIO);
498     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
499     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
500     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
501       List.of(
502         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.toNano(), 10),
503         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 12),
504         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 23),
505         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 23),
506         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 16),
507         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 23),
508         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 21),
509         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 16)
510       )
511     );
512 
513     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
514     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
515       InstantHelper.fromGermanDate("01.01.2024").toNano(),
516       instantHelper.addSeconds(2).toNano(),
517       null,
518       null,
519       AggregateFunction.STDDEV
520     );
521     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
522 
523     assertEquals(1, actual.size());
524     assertEquals(5.2372293656638, ((BigDecimal) actual.get(0).getValue()).doubleValue(), doubleEpsilon);
525   }
526 
527   @Test
528   @Transactional
529   public void getDataPointsByTimeseries_getMax_returnsMax_noFill_groupBy_integer() {
530     User user = new User("Testuser");
531     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
532     containerIO.setName(containerName);
533 
534     when(userService.getCurrentUser()).thenReturn(user);
535     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
536 
537     var container = timeseriesContainerService.createContainer(containerIO);
538     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
539     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
540     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
541       List.of(
542         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.toNano(), 21),
543         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 22),
544         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 23)
545       )
546     );
547 
548     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
549     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
550       InstantHelper.fromGermanDate("01.01.2024").toNano(),
551       instantHelper.addSeconds(2).toNano(),
552       Duration.ofMinutes(2).toNanos(),
553       null,
554       AggregateFunction.MAX
555     );
556     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
557 
558     assertEquals(1, actual.size());
559     assertEquals(23L, actual.get(0).getValue());
560   }
561 
562   /*
563    * Test aggregate functions with options of fill and groupBy
564    */
565 
566   @Test
567   @Transactional
568   public void getDataPointsByTimeseries_getMax_returnsMax_noFill_groupBy() {
569     User user = new User("Testuser");
570     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
571     containerIO.setName(containerName);
572 
573     when(userService.getCurrentUser()).thenReturn(user);
574     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
575 
576     var container = timeseriesContainerService.createContainer(containerIO);
577     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
578     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
579     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
580       List.of(
581         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
582         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2),
583         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3)
584       )
585     );
586 
587     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
588     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
589       InstantHelper.fromGermanDate("01.01.2024").toNano(),
590       InstantHelper.now().toNano(),
591       Duration.ofMinutes(2).toNanos(),
592       null,
593       AggregateFunction.MAX
594     );
595     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
596 
597     assertEquals(1, actual.size());
598     assertEquals(22.3, (Double) actual.get(0).getValue(), doubleEpsilon);
599   }
600 
601   @Test
602   @Transactional
603   public void getDataPointsByTimeseries_getMax_returnMax_prevFill_groupBy() {
604     User user = new User("Testuser");
605     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
606     containerIO.setName(containerName);
607 
608     when(userService.getCurrentUser()).thenReturn(user);
609     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
610 
611     var container = timeseriesContainerService.createContainer(containerIO);
612     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
613     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
614     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
615       List.of(
616         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
617         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(4).toNano(), 22.5),
618         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(4).toNano(), 22.3),
619         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(4).toNano(), 22.2)
620       )
621     );
622 
623     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
624     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
625       InstantHelper.fromGermanDate("01.01.2024").toNano(),
626       InstantHelper.fromGermanDate("01.01.2024").addSeconds(10).toNano(),
627       Duration.ofSeconds(2).toNanos(),
628       FillOption.PREVIOUS,
629       AggregateFunction.MAX
630     );
631     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
632 
633     assertEquals(6, actual.size());
634     assertEquals(22.1, (Double) actual.get(0).getValue(), doubleEpsilon);
635     assertEquals(22.1, (Double) actual.get(1).getValue(), doubleEpsilon);
636     assertEquals(22.5, (Double) actual.get(2).getValue(), doubleEpsilon);
637     assertEquals(22.5, (Double) actual.get(3).getValue(), doubleEpsilon);
638     assertEquals(22.3, (Double) actual.get(4).getValue(), doubleEpsilon);
639     assertEquals(22.3, (Double) actual.get(5).getValue(), doubleEpsilon);
640   }
641 
642   @Test
643   @Transactional
644   public void getDataPointsByTimeseries_noFunc_noFill_noGroupBy() {
645     User user = new User("Testuser");
646     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
647     containerIO.setName(containerName);
648 
649     when(userService.getCurrentUser()).thenReturn(user);
650     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
651 
652     var container = timeseriesContainerService.createContainer(containerIO);
653     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
654     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
655     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
656       List.of(
657         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
658         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
659         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.2)
660       )
661     );
662 
663     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
664     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
665       InstantHelper.fromGermanDate("01.01.2024").toNano(),
666       InstantHelper.fromGermanDate("01.01.2024").addSeconds(5).toNano(),
667       null,
668       null,
669       null
670     );
671     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
672 
673     assertEquals(3, actual.size());
674     assertEquals(22.1, (Double) actual.get(0).getValue(), doubleEpsilon);
675     assertEquals(22.3, (Double) actual.get(1).getValue(), doubleEpsilon);
676     assertEquals(22.2, (Double) actual.get(2).getValue(), doubleEpsilon);
677   }
678 
679   @Test
680   @Transactional
681   public void getDataPointsByTimeseries_noFunc_noFill_noGroupBy_boolean() {
682     User user = new User("Testuser");
683     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
684     containerIO.setName(containerName);
685 
686     when(userService.getCurrentUser()).thenReturn(user);
687     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
688 
689     var container = timeseriesContainerService.createContainer(containerIO);
690     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
691     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
692     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
693       List.of(
694         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.toNano(), true),
695         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(1).toNano(), false),
696         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(1).toNano(), true)
697       )
698     );
699 
700     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
701     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
702       InstantHelper.fromGermanDate("01.01.2024").toNano(),
703       InstantHelper.now().toNano(),
704       null,
705       null,
706       null
707     );
708     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
709 
710     assertEquals(3, actual.size());
711     assertEquals(true, actual.get(0).getValue());
712     assertEquals(false, actual.get(1).getValue());
713     assertEquals(true, actual.get(2).getValue());
714   }
715 
716   @Test
717   @Transactional
718   public void getDataPointsByTimeseries_noFunc_noFill_noGroupBy_string() {
719     User user = new User("Testuser");
720     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
721     containerIO.setName(containerName);
722 
723     when(userService.getCurrentUser()).thenReturn(user);
724     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
725 
726     var container = timeseriesContainerService.createContainer(containerIO);
727     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
728     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
729     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
730       List.of(
731         TimeseriesTestDataGenerator.generateDataPointString(instantHelper.toNano(), "Hello"),
732         TimeseriesTestDataGenerator.generateDataPointString(instantHelper.addSeconds(1).toNano(), "World"),
733         TimeseriesTestDataGenerator.generateDataPointString(instantHelper.addSeconds(1).toNano(), "!")
734       )
735     );
736 
737     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
738     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
739       InstantHelper.fromGermanDate("01.01.2024").toNano(),
740       InstantHelper.now().toNano(),
741       null,
742       null,
743       null
744     );
745     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
746 
747     assertEquals(3, actual.size());
748     assertEquals("Hello", actual.get(0).getValue());
749     assertEquals("World", actual.get(1).getValue());
750     assertEquals("!", actual.get(2).getValue());
751   }
752 
753   @Test
754   @Transactional
755   public void getDataPointsByTimeseries_noFunc_noFill_noGroupBy_integer() {
756     User user = new User("Testuser");
757     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
758     containerIO.setName(containerName);
759 
760     when(userService.getCurrentUser()).thenReturn(user);
761     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
762 
763     var container = timeseriesContainerService.createContainer(containerIO);
764     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
765     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
766     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
767       List.of(
768         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.toNano(), 1),
769         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 2),
770         TimeseriesTestDataGenerator.generateDataPointInteger(instantHelper.addSeconds(1).toNano(), 3)
771       )
772     );
773 
774     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
775     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
776       InstantHelper.fromGermanDate("01.01.2024").toNano(),
777       InstantHelper.now().toNano(),
778       null,
779       null,
780       null
781     );
782     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
783 
784     assertEquals(3, actual.size());
785     assertEquals(1L, actual.get(0).getValue());
786     assertEquals(2L, actual.get(1).getValue());
787     assertEquals(3L, actual.get(2).getValue());
788   }
789 
790   @Test
791   @Transactional
792   public void getDataPointsByTimeseries_getMax_returnMax_nullFill_groupBy() {
793     User user = new User("Testuser");
794     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
795     containerIO.setName(containerName);
796 
797     when(userService.getCurrentUser()).thenReturn(user);
798     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
799 
800     var container = timeseriesContainerService.createContainer(containerIO);
801     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
802     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
803     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
804       List.of(
805         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
806         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.5),
807         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
808         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(4).toNano(), 22.2)
809       )
810     );
811 
812     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
813     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
814       InstantHelper.fromGermanDate("01.01.2024").toNano(),
815       InstantHelper.fromGermanDate("01.01.2024").addSeconds(10).toNano(),
816       Duration.ofSeconds(2).toNanos(),
817       FillOption.NULL,
818       AggregateFunction.MAX
819     );
820     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
821 
822     assertEquals(6, actual.size());
823     assertEquals(22.5, (Double) actual.get(0).getValue(), doubleEpsilon);
824     assertEquals(22.3, (Double) actual.get(1).getValue(), doubleEpsilon);
825     assertEquals(null, actual.get(2).getValue());
826     assertEquals(22.2, (Double) actual.get(3).getValue(), doubleEpsilon);
827     assertEquals(null, actual.get(4).getValue());
828     assertEquals(null, actual.get(5).getValue());
829   }
830 
831   @Test
832   @Transactional
833   public void getDataPointsByTimeseries_getMax_returnMax_linearFill_groupBy() {
834     User user = new User("Testuser");
835     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
836     containerIO.setName(containerName);
837 
838     when(userService.getCurrentUser()).thenReturn(user);
839     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
840 
841     var container = timeseriesContainerService.createContainer(containerIO);
842     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
843     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
844     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
845       List.of(
846         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
847         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.5),
848         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(2).toNano(), 22.3),
849         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(5).toNano(), 22.15)
850       )
851     );
852 
853     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
854     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
855       InstantHelper.fromGermanDate("01.01.2024").toNano(),
856       InstantHelper.fromGermanDate("01.01.2024").addSeconds(10).toNano(),
857       Duration.ofSeconds(2).toNanos(),
858       FillOption.LINEAR,
859       AggregateFunction.MAX
860     );
861     var actual = this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
862 
863     assertEquals(6, actual.size());
864     assertEquals(22.5, (Double) actual.get(0).getValue(), doubleEpsilon);
865     assertEquals(22.3, (Double) actual.get(1).getValue(), doubleEpsilon);
866     assertEquals(22.25, (Double) actual.get(2).getValue(), doubleEpsilon);
867     assertEquals(22.2, (Double) actual.get(3).getValue(), doubleEpsilon);
868     assertEquals(22.15, (Double) actual.get(4).getValue(), doubleEpsilon);
869     assertEquals(null, actual.get(5).getValue());
870   }
871 
872   /*
873    * Aggregate Function Exceptions
874    */
875 
876   @Test
877   @Transactional
878   public void getDataPointsByTimeseries_getMax_returnsException_noFill_groupBy_boolean() {
879     User user = new User("Testuser");
880     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
881     containerIO.setName(containerName);
882 
883     when(userService.getCurrentUser()).thenReturn(user);
884     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
885 
886     var container = timeseriesContainerService.createContainer(containerIO);
887     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
888     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
889     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
890       List.of(
891         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.toNano(), true),
892         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(1).toNano(), false),
893         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(1).toNano(), true)
894       )
895     );
896 
897     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
898     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
899       InstantHelper.fromGermanDate("01.01.2024").toNano(),
900       instantHelper.addSeconds(3).toNano(),
901       Duration.ofMinutes(2).toNanos(),
902       null,
903       AggregateFunction.MAX
904     );
905     // Booleans must not use aggregation
906     assertThrowsExactly(InvalidRequestException.class, () -> {
907       this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
908     });
909   }
910 
911   @Test
912   @Transactional
913   public void getDataPointsByTimeseries_getMax_returnsException_noFill_groupBy_string() {
914     User user = new User("Testuser");
915     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
916     containerIO.setName(containerName);
917 
918     when(userService.getCurrentUser()).thenReturn(user);
919     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
920 
921     var container = timeseriesContainerService.createContainer(containerIO);
922     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
923     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
924     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
925       List.of(
926         TimeseriesTestDataGenerator.generateDataPointString(instantHelper.toNano(), "Hello"),
927         TimeseriesTestDataGenerator.generateDataPointString(instantHelper.addSeconds(1).toNano(), "World"),
928         TimeseriesTestDataGenerator.generateDataPointString(instantHelper.addSeconds(1).toNano(), "!")
929       )
930     );
931 
932     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
933     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
934       InstantHelper.fromGermanDate("01.01.2024").toNano(),
935       instantHelper.addSeconds(3).toNano(),
936       Duration.ofMinutes(2).toNanos(),
937       null,
938       AggregateFunction.MAX
939     );
940     // Strings must not use aggregation
941     assertThrowsExactly(InvalidRequestException.class, () -> {
942       this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
943     });
944   }
945 
946   @Test
947   @Transactional
948   public void getDataPointsByTimeseries_returnsException_noFunc_prevFill_groupBy() {
949     User user = new User("Testuser");
950     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
951     containerIO.setName(containerName);
952 
953     when(userService.getCurrentUser()).thenReturn(user);
954     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
955 
956     var container = timeseriesContainerService.createContainer(containerIO);
957     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
958     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
959     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
960       List.of(
961         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
962         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(6).toNano(), 22.3),
963         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(9).toNano(), 22.2)
964       )
965     );
966 
967     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
968     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
969       InstantHelper.fromGermanDate("01.01.2024").toNano(),
970       InstantHelper.fromGermanDate("01.01.2024").addSeconds(5).toNano(),
971       Duration.ofSeconds(3).toNanos(),
972       FillOption.PREVIOUS,
973       null
974     );
975     // Filling/ Grouping without specifying aggregation function is not allowed
976     assertThrowsExactly(InvalidRequestException.class, () -> {
977       this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
978     });
979   }
980 
981   @Test
982   @Transactional
983   public void getDataPointsByTimeseries_getMax_returnsException_linearFill_noGroupBy() {
984     User user = new User("Testuser");
985     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
986     containerIO.setName(containerName);
987 
988     when(userService.getCurrentUser()).thenReturn(user);
989     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
990 
991     var container = timeseriesContainerService.createContainer(containerIO);
992     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
993     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
994     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
995       List.of(
996         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 22.1),
997         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 22.3),
998         TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(2).toNano(), 22.2)
999       )
1000     );
1001 
1002     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
1003     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
1004       InstantHelper.fromGermanDate("01.01.2024").toNano(),
1005       InstantHelper.fromGermanDate("01.01.2024").addSeconds(5).toNano(),
1006       null,
1007       FillOption.LINEAR,
1008       AggregateFunction.MAX
1009     );
1010     // Setting fill option, without specifying groupBy/ interval is not allowed
1011     assertThrowsExactly(InvalidRequestException.class, () -> {
1012       this.timeseriesService.getDataPointsByTimeseries(container.getId(), timeseries, queryParams);
1013     });
1014   }
1015 }