-
Notifications
You must be signed in to change notification settings - Fork 5
/
ProcessorProviderTest.groovy
275 lines (244 loc) · 11.8 KB
/
ProcessorProviderTest.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/*
* © 2021. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.processor
import edu.ie3.datamodel.exceptions.ProcessorProviderException
import edu.ie3.datamodel.io.processor.result.ResultEntityProcessor
import edu.ie3.datamodel.io.processor.timeseries.TimeSeriesProcessor
import edu.ie3.datamodel.io.processor.timeseries.TimeSeriesProcessorKey
import edu.ie3.datamodel.io.source.TimeSeriesMappingSource
import edu.ie3.datamodel.models.StandardUnits
import edu.ie3.datamodel.models.input.MeasurementUnitInput
import edu.ie3.datamodel.models.input.NodeInput
import edu.ie3.datamodel.models.input.OperatorInput
import edu.ie3.datamodel.models.input.RandomLoadParameters
import edu.ie3.datamodel.models.input.connector.LineInput
import edu.ie3.datamodel.models.input.connector.SwitchInput
import edu.ie3.datamodel.models.input.connector.Transformer2WInput
import edu.ie3.datamodel.models.input.connector.Transformer3WInput
import edu.ie3.datamodel.models.input.connector.type.LineTypeInput
import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput
import edu.ie3.datamodel.models.input.connector.type.Transformer3WTypeInput
import edu.ie3.datamodel.models.input.graphics.LineGraphicInput
import edu.ie3.datamodel.models.input.graphics.NodeGraphicInput
import edu.ie3.datamodel.models.input.system.*
import edu.ie3.datamodel.models.input.system.type.*
import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput
import edu.ie3.datamodel.models.input.thermal.ThermalBusInput
import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput
import edu.ie3.datamodel.models.result.NodeResult
import edu.ie3.datamodel.models.result.connector.LineResult
import edu.ie3.datamodel.models.result.connector.SwitchResult
import edu.ie3.datamodel.models.result.connector.Transformer2WResult
import edu.ie3.datamodel.models.result.connector.Transformer3WResult
import edu.ie3.datamodel.models.result.system.*
import edu.ie3.datamodel.models.result.thermal.CylindricalStorageResult
import edu.ie3.datamodel.models.result.thermal.ThermalHouseResult
import edu.ie3.datamodel.models.timeseries.IntValue
import edu.ie3.datamodel.models.timeseries.TimeSeries
import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry
import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileInput
import edu.ie3.datamodel.models.value.*
import edu.ie3.test.common.TimeSeriesTestData
import edu.ie3.util.TimeUtil
import spock.lang.Specification
import tech.units.indriya.quantity.Quantities
import javax.measure.Quantity
import javax.measure.quantity.Power
class ProcessorProviderTest extends Specification implements TimeSeriesTestData {
def "A ProcessorProvider should initialize all known EntityProcessors by default"() {
given:
ProcessorProvider provider = new ProcessorProvider()
List knownEntityProcessors = [
/* InputEntity */
OperatorInput,
RandomLoadParameters,
TimeSeriesMappingSource.MappingEntry,
/* - AssetInput */
NodeInput,
LineInput,
Transformer2WInput,
Transformer3WInput,
SwitchInput,
MeasurementUnitInput,
ThermalBusInput,
/* -- SystemParticipantInput */
ChpInput,
BmInput,
EvInput,
EvcsInput,
FixedFeedInInput,
HpInput,
LoadInput,
PvInput,
StorageInput,
WecInput,
EmInput,
/* -- ThermalUnitInput */
ThermalHouseInput,
CylindricalStorageInput,
/* - GraphicInput */
NodeGraphicInput,
LineGraphicInput,
/* - AssetTypeInput */
BmTypeInput,
ChpTypeInput,
EvTypeInput,
HpTypeInput,
LineTypeInput,
Transformer2WTypeInput,
Transformer3WTypeInput,
StorageTypeInput,
WecTypeInput,
/* ResultEntity */
FixedFeedInResult,
HpResult,
BmResult,
PvResult,
ChpResult,
WecResult,
StorageResult,
EvcsResult,
EvResult,
EmResult,
FlexOptionsResult,
Transformer2WResult,
Transformer3WResult,
LineResult,
LoadResult,
SwitchResult,
NodeResult,
ThermalHouseResult,
CylindricalStorageResult
]
// currently known processors
expect:
provider.registeredClasses.size() == knownEntityProcessors.size()
provider.registeredClasses.sort() == knownEntityProcessors.sort()
}
def "A ProcessorProvider should initialize all known TimeSeriesProcessors by default"() {
given:
ProcessorProvider provider = new ProcessorProvider()
Set expected = [
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, SolarIrradianceValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, TemperatureValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, WindValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, WeatherValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, HeatDemandValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, PValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, HeatAndPValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, SValue),
new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, HeatAndSValue),
new TimeSeriesProcessorKey(LoadProfileInput, LoadProfileEntry, PValue)
] as Set
when:
Set<TimeSeriesProcessorKey> actual = provider.getRegisteredTimeSeriesCombinations()
then:
actual == expected
}
def "A ProcessorProvider should return the header elements for a entity class known by one of its processors and do nothing otherwise"() {
given:
ProcessorProvider provider = new ProcessorProvider([
new ResultEntityProcessor(PvResult),
new ResultEntityProcessor(EvResult)
], [] as Map<TimeSeriesProcessorKey, TimeSeriesProcessor<TimeSeries<TimeSeriesEntry<Value>, Value>, TimeSeriesEntry<Value>, Value>>)
when:
String[] headerResults = provider.getHeaderElements(PvResult)
then:
headerResults == [
"uuid",
"inputModel",
"p",
"q",
"time"
] as String[]
when:
provider.getHeaderElements(WecResult)
then:
ProcessorProviderException exception = thrown(ProcessorProviderException)
exception.message == "Error during determination of header elements for entity class 'WecResult'."
}
def "A ProcessorProvider should return the header elements for a time series key known by one of its processors and do nothing otherwise"() {
given:
TimeSeriesProcessorKey availableKey = new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue)
Map<TimeSeriesProcessorKey, TimeSeriesProcessor<TimeSeries<TimeSeriesEntry<Value>, Value>, TimeSeriesEntry<Value>, Value>> timeSeriesProcessors = new HashMap<>()
timeSeriesProcessors.put(availableKey, new TimeSeriesProcessor<>(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue))
ProcessorProvider provider = new ProcessorProvider([], timeSeriesProcessors)
when:
String[] headerResults = provider.getHeaderElements(availableKey)
then:
headerResults == [
"uuid",
"price",
"time"
] as String[]
when:
provider.getHeaderElements(new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, IntValue))
then:
ProcessorProviderException exception = thrown(ProcessorProviderException)
exception.message == "Error during determination of header elements for time series combination 'TimeSeriesProcessorKey{timeSeriesClass=class edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries, entryClass=class edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue, valueClass=class edu.ie3.datamodel.models.timeseries.IntValue}'."
}
def "A ProcessorProvider should process an entity known by its underlying processors correctly and do nothing otherwise"() {
given:
ProcessorProvider provider = new ProcessorProvider([
new ResultEntityProcessor(PvResult),
new ResultEntityProcessor(EvResult)
], [] as Map<TimeSeriesProcessorKey, TimeSeriesProcessor<TimeSeries<TimeSeriesEntry<Value>, Value>, TimeSeriesEntry<Value>, Value>>)
Map expectedMap = ["uuid" : "22bea5fc-2cb2-4c61-beb9-b476e0107f52",
"inputModel": "22bea5fc-2cb2-4c61-beb9-b476e0107f52",
"p" : "0.01",
"q" : "0.01",
"time" : "2020-01-30T17:26:44Z[UTC]"]
when:
UUID uuid = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52")
UUID inputModel = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52")
Quantity<Power> p = Quantities.getQuantity(10, StandardUnits.ACTIVE_POWER_IN)
Quantity<Power> q = Quantities.getQuantity(10, StandardUnits.REACTIVE_POWER_IN)
PvResult pvResult = new PvResult(uuid, TimeUtil.withDefaults.toZonedDateTime("2020-01-30 17:26:44"), inputModel, p, q)
and:
LinkedHashMap<String, String> resultMap = provider.handleEntity(pvResult)
then:
resultMap.size() == 5
resultMap == expectedMap
when:
provider.handleEntity(new WecResult(uuid, TimeUtil.withDefaults.toZonedDateTime("2020-01-30 17:26:44"), inputModel, p, q))
then:
Exception ex = thrown()
ex.class == ProcessorProviderException
List.of("Cannot find a suitable processor for provided class with name 'WecResult'. This provider's processors can process: ","PvResult", "EvResult")
.forEach {str -> ex.message.contains(str)}
}
def "A ProcessorProvider returns an empty Optional, if none of the assigned processors is able to handle a time series"() {
given:
TimeSeriesProcessorKey key = new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue)
TimeSeriesProcessor<IndividualTimeSeries, TimeBasedValue, EnergyPriceValue> processor = new TimeSeriesProcessor<>(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue)
Map<TimeSeriesProcessorKey, TimeSeriesProcessor> timeSeriesProcessorMap = new HashMap<>()
timeSeriesProcessorMap.put(key, processor)
ProcessorProvider provider = new ProcessorProvider([], timeSeriesProcessorMap)
when:
provider.handleTimeSeries(individualIntTimeSeries)
then:
Exception ex = thrown()
ex.class == ProcessorProviderException
ex.message == "Cannot handle the time series {" + individualIntTimeSeries + "}."
ex.cause.message == "Cannot find processor for time series combination 'TimeSeriesProcessorKey{timeSeriesClass=class edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries, entryClass=class edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue, valueClass=class edu.ie3.datamodel.models.timeseries.IntValue}'. Either your provider is not properly initialized or there is no implementation to process this entity class!)"
}
def "A ProcessorProvider handles a time series correctly"() {
given:
TimeSeriesProcessorKey key = new TimeSeriesProcessorKey(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue)
TimeSeriesProcessor<IndividualTimeSeries, TimeBasedValue, EnergyPriceValue> processor = new TimeSeriesProcessor<>(IndividualTimeSeries, TimeBasedValue, EnergyPriceValue)
Map<TimeSeriesProcessorKey, TimeSeriesProcessor> timeSeriesProcessorMap = new HashMap<>()
timeSeriesProcessorMap.put(key, processor)
ProcessorProvider provider = new ProcessorProvider([], timeSeriesProcessorMap)
when:
Set<LinkedHashMap<String, String>> actual = provider.handleTimeSeries(individualEnergyPriceTimeSeries)
then:
actual == individualEnergyPriceTimeSeriesProcessed
}
}