View Javadoc
1   package de.dlr.shepard.data.timeseries.utilities;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertThrows;
5   import static org.junit.jupiter.api.Assertions.assertTrue;
6   
7   import de.dlr.shepard.common.exceptions.InvalidBodyException;
8   import de.dlr.shepard.data.timeseries.TimeseriesTestDataGenerator;
9   import de.dlr.shepard.data.timeseries.io.TimeseriesWithDataPoints;
10  import de.dlr.shepard.data.timeseries.model.Timeseries;
11  import de.dlr.shepard.data.timeseries.model.TimeseriesDataPoint;
12  import de.dlr.shepard.data.timeseries.services.TimeseriesCsvService;
13  import jakarta.inject.Inject;
14  import java.io.ByteArrayInputStream;
15  import java.io.IOException;
16  import java.io.InputStream;
17  import java.nio.charset.StandardCharsets;
18  import java.util.ArrayList;
19  import java.util.List;
20  import org.apache.commons.io.IOUtils;
21  import org.junit.jupiter.api.Test;
22  
23  public class CsvConverterTest {
24  
25    @Inject
26    TimeseriesCsvService timeseriesService;
27  
28    @Test
29    void testConvertToCsv_multipleTypes_success() throws IOException {
30      var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
31      List<TimeseriesDataPoint> dataPoints = new ArrayList<>(
32        List.of(
33          new TimeseriesDataPoint(88551122, 22.1),
34          new TimeseriesDataPoint(88551123, 4),
35          new TimeseriesDataPoint(88551124, 22.2),
36          new TimeseriesDataPoint(88551125, true),
37          new TimeseriesDataPoint(88551126, "Hello World")
38        )
39      );
40  
41      String expectedCsvString =
42        """
43        DEVICE,FIELD,LOCATION,MEASUREMENT,SYMBOLICNAME,TIMESTAMP,VALUE
44        device,field,location,temperature,symbolicName,88551122,22.1
45        device,field,location,temperature,symbolicName,88551123,4
46        device,field,location,temperature,symbolicName,88551124,22.2
47        device,field,location,temperature,symbolicName,88551125,true
48        device,field,location,temperature,symbolicName,88551126,Hello World
49        """;
50  
51      String actualCsvString = IOUtils.toString(
52        CsvConverter.convertToCsv(timeseries, dataPoints),
53        StandardCharsets.UTF_8
54      );
55  
56      assertEquals(expectedCsvString, actualCsvString);
57    }
58  
59    @Test
60    void testConvertToCsv_emptyData_success() throws IOException {
61      var timeseries = TimeseriesTestDataGenerator.generateTimeseries("temperature");
62      List<TimeseriesDataPoint> dataPoints = new ArrayList<>();
63  
64      String expectedCsvString = "";
65  
66      String actualCsvString = IOUtils.toString(
67        CsvConverter.convertToCsv(timeseries, dataPoints),
68        StandardCharsets.UTF_8
69      );
70  
71      assertEquals(expectedCsvString, actualCsvString);
72    }
73  
74    @Test
75    void testConvertToTimeseriesWithData_multipleTypes_success() throws IOException {
76      String actualCsvString =
77        """
78        DEVICE,FIELD,LOCATION,MEASUREMENT,SYMBOLICNAME,TIMESTAMP,VALUE
79        device,field,location,double,symbolicName,88551122,22.1
80        device,field,location,integer,symbolicName,88551123,4
81        device,field,location,double,symbolicName,88551124,22.2
82        device,field,location,boolean,symbolicName,88551125,true
83        device,field,location,integer,symbolicName,88551126,5
84        device,field,location,string,symbolicName,88551127,Hello World
85        device,field,location,boolean,symbolicName,88551128,false
86        """;
87  
88      var expectedTimeseriesDouble = new Timeseries("double", "device", "location", "symbolicName", "field");
89      var expectedTimeseriesInteger = new Timeseries("integer", "device", "location", "symbolicName", "field");
90      var expectedTimeseriesBoolean = new Timeseries("boolean", "device", "location", "symbolicName", "field");
91      var expectedTimeseriesString = new Timeseries("string", "device", "location", "symbolicName", "field");
92  
93      List<TimeseriesDataPoint> expectedDataPointsIODouble = new ArrayList<>(
94        List.of(new TimeseriesDataPoint(88551122, 22.1), new TimeseriesDataPoint(88551124, 22.2))
95      );
96  
97      List<TimeseriesDataPoint> expectedDataPointsIOInteger = new ArrayList<>(
98        List.of(new TimeseriesDataPoint(88551123, 4), new TimeseriesDataPoint(88551126, 5))
99      );
100 
101     List<TimeseriesDataPoint> expectedDataPointsIOBoolean = new ArrayList<>(
102       List.of(new TimeseriesDataPoint(88551125, true), new TimeseriesDataPoint(88551128, false))
103     );
104 
105     List<TimeseriesDataPoint> expectedDataPointsIOString = new ArrayList<>(
106       List.of(new TimeseriesDataPoint(88551127, "Hello World"))
107     );
108 
109     InputStream timeseriesDataStream = new ByteArrayInputStream(actualCsvString.getBytes(StandardCharsets.UTF_8));
110 
111     List<TimeseriesWithDataPoints> actualTimeseriesWithDataPointsList = CsvConverter.convertToTimeseriesWithData(
112       timeseriesDataStream
113     );
114     List<TimeseriesWithDataPoints> expectedTimeseriesWithDataPointsList = List.of(
115       new TimeseriesWithDataPoints(expectedTimeseriesBoolean, expectedDataPointsIOBoolean),
116       new TimeseriesWithDataPoints(expectedTimeseriesInteger, expectedDataPointsIOInteger),
117       new TimeseriesWithDataPoints(expectedTimeseriesString, expectedDataPointsIOString),
118       new TimeseriesWithDataPoints(expectedTimeseriesDouble, expectedDataPointsIODouble)
119     );
120 
121     assertEquals(4, actualTimeseriesWithDataPointsList.size());
122     assertTrue(actualTimeseriesWithDataPointsList.containsAll(expectedTimeseriesWithDataPointsList));
123     assertTrue(expectedTimeseriesWithDataPointsList.containsAll(actualTimeseriesWithDataPointsList));
124   }
125 
126   @Test
127   void testConvertToTimeseriesWithData_emptyData() throws IOException {
128     String actualCsvString = "DEVICE,FIELD,LOCATION,MEASUREMENT,SYMBOLICNAME,TIMESTAMP,VALUE";
129     InputStream timeseriesDataStream = new ByteArrayInputStream(actualCsvString.getBytes(StandardCharsets.UTF_8));
130     var actualTimeseriesDataIOMap = CsvConverter.convertToTimeseriesWithData(timeseriesDataStream);
131     assertEquals(0, actualTimeseriesDataIOMap.size());
132   }
133 
134   @Test
135   void testConvertToTimeseriesWithData_csvFormatError_failure() throws IOException {
136     String wrongFormatCSV =
137       """
138       DEVICE,FIELD,LOCATION,MEASUREMENT,SYMBOLICNAME,TIMESTAMP,VALUE
139       device,field,location,double,symbolicName,88551122,22.1,,
140       device,field,location,integer,symbolicName,88551123,4
141       device,field,location,boolean,symbolicName,88551128,false
142       """;
143 
144     InputStream timeseriesDataStream = new ByteArrayInputStream(wrongFormatCSV.getBytes(StandardCharsets.UTF_8));
145 
146     // this RuntimeException is a InvalidBodyException wrapped into a runtime exception
147     RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
148       CsvConverter.convertToTimeseriesWithData(timeseriesDataStream);
149     });
150 
151     Throwable cause = thrown.getCause();
152     assertEquals(InvalidBodyException.class, cause.getClass());
153     assertEquals("Number of data fields does not match number of headers.", cause.getMessage());
154   }
155 }