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.assertTrue;
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.data.timeseries.TimeseriesTestDataGenerator;
11  import de.dlr.shepard.data.timeseries.io.TimeseriesContainerIO;
12  import de.dlr.shepard.data.timeseries.io.TimeseriesWithDataPoints;
13  import de.dlr.shepard.data.timeseries.model.Timeseries;
14  import de.dlr.shepard.data.timeseries.model.TimeseriesDataPoint;
15  import de.dlr.shepard.data.timeseries.model.TimeseriesDataPointsQueryParams;
16  import de.dlr.shepard.data.timeseries.model.TimeseriesEntity;
17  import de.dlr.shepard.data.timeseries.utilities.CsvConverter;
18  import io.quarkus.test.InjectMock;
19  import io.quarkus.test.junit.QuarkusTest;
20  import jakarta.inject.Inject;
21  import jakarta.transaction.Transactional;
22  import java.io.BufferedReader;
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.InputStreamReader;
26  import java.net.URISyntaxException;
27  import java.nio.file.Files;
28  import java.util.ArrayList;
29  import java.util.List;
30  import org.junit.jupiter.api.Test;
31  
32  @QuarkusTest
33  public class TimeseriesCsvServiceTest {
34  
35    @InjectMock
36    UserService userService;
37  
38    @InjectMock
39    AuthenticationContext authenticationContext;
40  
41    @Inject
42    TimeseriesContainerService timeseriesContainerService;
43  
44    @Inject
45    TimeseriesService timeseriesService;
46  
47    @Inject
48    TimeseriesCsvService timeseriesCsvService;
49  
50    private final String containerName = "AnotherContainer";
51  
52    /**********************
53     * exportTimeseriesDataToCsv
54     ***********************/
55  
56    @Test
57    @Transactional
58    public void exportTimeseriesDataToCsv_oneTimeseriesWithDoubleValues_success() throws IOException, URISyntaxException {
59      User user = new User("Testuser");
60      TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
61      containerIO.setName(containerName);
62  
63      when(userService.getCurrentUser()).thenReturn(user);
64      when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
65  
66      var container = timeseriesContainerService.createContainer(containerIO);
67      var timeseries = TimeseriesTestDataGenerator.generateTimeseries("water_level");
68      InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
69      List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
70        List.of(
71          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.toNano(), 90.0),
72          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(1).toNano(), 120.57),
73          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(2).toNano(), 127.25),
74          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(3).toNano(), 129.25),
75          TimeseriesTestDataGenerator.generateDataPointDouble(instantHelper.addSeconds(4).toNano(), 134.0)
76        )
77      );
78  
79      this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
80      TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
81        InstantHelper.fromGermanDate("01.01.2024").toNano(),
82        instantHelper.toNano(),
83        null,
84        null,
85        null
86      );
87      var actual = this.timeseriesCsvService.exportTimeseriesDataToCsv(container.getId(), timeseries, queryParams);
88  
89      StringBuilder actualCsvContent = new StringBuilder();
90      try (BufferedReader reader = new BufferedReader(new InputStreamReader(actual))) {
91        String line;
92        while ((line = reader.readLine()) != null) {
93          actualCsvContent.append(line).append("\n");
94        }
95      }
96  
97      var expectedCsvFile = new File(
98        getClass().getClassLoader().getResource("timeseries_export_experimental_double.csv").toURI()
99      );
100     var expectedCsvContent = Files.readString(expectedCsvFile.toPath());
101 
102     assertEquals(actualCsvContent.toString().trim(), expectedCsvContent.trim());
103   }
104 
105   @Test
106   @Transactional
107   public void exportTimeseriesDataToCsv_oneTimeseriesWithStringValues_success() throws IOException, URISyntaxException {
108     User user = new User("Testuser");
109     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
110     containerIO.setName(containerName);
111 
112     when(userService.getCurrentUser()).thenReturn(user);
113     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
114 
115     var container = timeseriesContainerService.createContainer(containerIO);
116     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("status");
117     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
118     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
119       List.of(TimeseriesTestDataGenerator.generateDataPointString(instantHelper.toNano(), "running"))
120     );
121 
122     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
123     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
124       instantHelper.toNano(),
125       instantHelper.addSeconds(2).toNano(),
126       null,
127       null,
128       null
129     );
130     var actual = this.timeseriesCsvService.exportTimeseriesDataToCsv(container.getId(), timeseries, queryParams);
131 
132     StringBuilder actualCsvContent = new StringBuilder();
133     try (BufferedReader reader = new BufferedReader(new InputStreamReader(actual))) {
134       String line;
135       while ((line = reader.readLine()) != null) {
136         actualCsvContent.append(line).append("\n");
137       }
138     }
139 
140     var expectedCsvFile = new File(
141       getClass().getClassLoader().getResource("timeseries_export_experimental_string.csv").toURI()
142     );
143     var expectedCsvContent = Files.readString(expectedCsvFile.toPath());
144 
145     assertEquals(actualCsvContent.toString().trim(), expectedCsvContent.trim());
146   }
147 
148   @Test
149   @Transactional
150   public void exportTimeseriesDataToCsv_oneTimeseriesWithBooleanValues_success()
151     throws IOException, URISyntaxException {
152     User user = new User("Testuser");
153     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
154     containerIO.setName(containerName);
155 
156     when(userService.getCurrentUser()).thenReturn(user);
157     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
158 
159     var container = timeseriesContainerService.createContainer(containerIO);
160     var timeseries = TimeseriesTestDataGenerator.generateTimeseries("motion");
161     InstantHelper instantHelper = InstantHelper.fromGermanDate("01.01.2024");
162     List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
163       List.of(
164         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.toNano(), true),
165         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(1).toNano(), false),
166         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(2).toNano(), true),
167         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(3).toNano(), false),
168         TimeseriesTestDataGenerator.generateDataPointBoolean(instantHelper.addSeconds(4).toNano(), true)
169       )
170     );
171 
172     this.timeseriesService.saveDataPoints(container.getId(), timeseries, dataPoints);
173     TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
174       InstantHelper.fromGermanDate("01.01.2024").toNano(),
175       instantHelper.toNano(),
176       null,
177       null,
178       null
179     );
180     var actual = this.timeseriesCsvService.exportTimeseriesDataToCsv(container.getId(), timeseries, queryParams);
181 
182     StringBuilder actualCsvContent = new StringBuilder();
183     try (BufferedReader reader = new BufferedReader(new InputStreamReader(actual))) {
184       String line;
185       while ((line = reader.readLine()) != null) {
186         actualCsvContent.append(line).append("\n");
187       }
188     }
189 
190     var expectedCsvFile = new File(
191       getClass().getClassLoader().getResource("timeseries_export_experimental_boolean.csv").toURI()
192     );
193     var expectedCsvContent = Files.readString(expectedCsvFile.toPath());
194 
195     assertEquals(actualCsvContent.toString().trim(), expectedCsvContent.trim());
196   }
197 
198   /**********************
199    * importTimeseriesFromCsv
200    ***********************/
201 
202   @Test
203   @Transactional
204   public void importTimeseriesFromCsv_multipleTimeseriesWithMultipleValues_success()
205     throws IOException, URISyntaxException {
206     User user = new User("Testuser");
207     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
208     containerIO.setName(containerName);
209 
210     when(userService.getCurrentUser()).thenReturn(user);
211     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
212 
213     var container = timeseriesContainerService.createContainer(containerIO);
214 
215     File importCSVFile = new File(
216       getClass().getClassLoader().getResource("timeseries_import_experimental.csv").toURI()
217     );
218 
219     String csvFileContent = Files.readString(importCSVFile.toPath());
220 
221     timeseriesCsvService.importTimeseriesFromCsv(container.getId(), importCSVFile.toPath().toString());
222 
223     List<TimeseriesEntity> availTimeseriesList = timeseriesService.getTimeseriesAvailable(container.getId());
224 
225     List<Timeseries> expTimeseries = new ArrayList<Timeseries>();
226 
227     for (var currTimeseries : availTimeseriesList) {
228       expTimeseries.add(
229         new Timeseries(
230           currTimeseries.getMeasurement(),
231           currTimeseries.getDevice(),
232           currTimeseries.getLocation(),
233           currTimeseries.getSymbolicName(),
234           currTimeseries.getField()
235         )
236       );
237     }
238 
239     var actualTimeseriesDataMap = new ArrayList<TimeseriesWithDataPoints>();
240     expTimeseries
241       .stream()
242       .forEach(timeseries -> {
243         actualTimeseriesDataMap.add(
244           new TimeseriesWithDataPoints(
245             timeseries,
246             timeseriesService.getDataPointsByTimeseries(
247               container.getId(),
248               timeseries,
249               new TimeseriesDataPointsQueryParams(
250                 InstantHelper.fromGermanDate("01.01.2024").addHours(-1).toNano(),
251                 InstantHelper.fromGermanDate("01.01.2024").addHours(1).toNano(),
252                 null,
253                 null,
254                 null
255               )
256             )
257           )
258         );
259       });
260 
261     var actualTimeSeriesStream = CsvConverter.convertToCsv(actualTimeseriesDataMap);
262 
263     int lineCounter = 0;
264 
265     try (BufferedReader reader = new BufferedReader(new InputStreamReader(actualTimeSeriesStream))) {
266       String line;
267       while ((line = reader.readLine()) != null) {
268         lineCounter += 1;
269         assertTrue(
270           csvFileContent.contains(line),
271           String.format("Line '%s' is not contained in original CSV file", line)
272         );
273       }
274     }
275     // make sure the number of lines in both CSV files are equal
276     assertEquals(csvFileContent.split("\n").length, lineCounter);
277   }
278 
279   @Test
280   @Transactional
281   public void importTimeseriesFromCsv_emptyTimeseries_noDataCreation() throws IOException, URISyntaxException {
282     User user = new User("Testuser");
283     TimeseriesContainerIO containerIO = new TimeseriesContainerIO();
284     containerIO.setName(containerName);
285 
286     when(userService.getCurrentUser()).thenReturn(user);
287     when(authenticationContext.getCurrentUserName()).thenReturn(user.getUsername());
288 
289     var container = timeseriesContainerService.createContainer(containerIO);
290 
291     File importCSVFile = new File(
292       getClass().getClassLoader().getResource("timeseries_import_experimental_empty.csv").toURI()
293     );
294 
295     timeseriesCsvService.importTimeseriesFromCsv(container.getId(), importCSVFile.toPath().toString());
296 
297     List<TimeseriesEntity> availTimeseriesList = timeseriesService.getTimeseriesAvailable(container.getId());
298 
299     assertEquals(
300       0,
301       availTimeseriesList.size(),
302       "Imported empty timeseries payload, but a timeseries was created from this empty payload."
303     );
304   }
305 }