-
Notifications
You must be signed in to change notification settings - Fork 5
/
ResultEntityProcessorTest.groovy
310 lines (245 loc) · 12.7 KB
/
ResultEntityProcessorTest.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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
* © 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.result
import edu.ie3.datamodel.exceptions.EntityProcessorException
import edu.ie3.datamodel.models.StandardUnits
import edu.ie3.datamodel.models.result.NodeResult
import edu.ie3.datamodel.models.result.ResultEntity
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.util.quantities.PowerSystemUnits
import spock.lang.Shared
import spock.lang.Specification
import tech.units.indriya.quantity.Quantities
import tech.units.indriya.unit.Units
import javax.measure.Quantity
import javax.measure.quantity.*
import java.time.ZonedDateTime
class ResultEntityProcessorTest extends Specification {
// static fields
@Shared
UUID uuid = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52")
@Shared
UUID inputModel = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52")
@Shared
Quantity<Power> p = Quantities.getQuantity(10, StandardUnits.ACTIVE_POWER_IN)
@Shared
Quantity<Power> q = Quantities.getQuantity(10, StandardUnits.REACTIVE_POWER_IN)
@Shared
Quantity<Dimensionless> soc = Quantities.getQuantity(50, Units.PERCENT)
@Shared
Quantity<Power> qDot = Quantities.getQuantity(1, StandardUnits.Q_DOT_RESULT)
@Shared
def expectedStandardResults = [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]']
@Shared
def expectedSocResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
p : '0.01',
q : '0.01',
soc : '50.0',
time : '2020-01-30T17:26:44Z[UTC]']
@Shared
def expectedQDotResults = [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]',
qDot : '1.0']
def "A ResultEntityProcessor should de-serialize a provided SystemParticipantResult correctly"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(modelClass)
def validResult = validSystemParticipantResult
when:
def validProcessedElement = sysPartResProcessor.handleEntity(validResult)
then:
validProcessedElement.present
validProcessedElement.get() == expectedResults
where:
modelClass | validSystemParticipantResult || expectedResults
LoadResult | new LoadResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
FixedFeedInResult | new FixedFeedInResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
BmResult | new BmResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
EvResult | new EvResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q, soc) || expectedSocResults
PvResult | new PvResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
EvcsResult | new EvcsResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
ChpResult | new ChpResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q, qDot) || expectedQDotResults
WecResult | new WecResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
StorageResult | new StorageResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q, soc) || expectedSocResults
HpResult | new HpResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q, qDot) || expectedQDotResults
EmResult | new EmResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q) || expectedStandardResults
}
def "A ResultEntityProcessor should throw an exception if the provided class is not registered"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(LoadResult)
def storageResult = new StorageResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, p, q, Quantities.getQuantity(10d, StandardUnits.SOC))
when:
sysPartResProcessor.handleEntity(storageResult)
then:
EntityProcessorException ex = thrown()
ex.message == "Cannot process StorageResult.class with this EntityProcessor. Please either provide an element of LoadResult.class or create a new processor for StorageResult.class!"
}
def "A ResultEntityProcessor should de-serialize a NodeResult correctly"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(NodeResult)
Quantity<Dimensionless> vMag = Quantities.getQuantity(0.95, PowerSystemUnits.PU)
Quantity<Angle> vAng = Quantities.getQuantity(45, StandardUnits.VOLTAGE_ANGLE)
def validResult = new NodeResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, vMag, vAng)
def expectedResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
vAng : '45.0',
vMag : '0.95',
time : '2020-01-30T17:26:44Z[UTC]']
when:
def validProcessedElement = sysPartResProcessor.handleEntity(validResult)
then:
validProcessedElement.present
validProcessedElement.get() == expectedResults
}
def "A ResultEntityProcessor should de-serialize a FlexOptionsResult correctly"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(FlexOptionsResult)
Quantity<Power> pReference = Quantities.getQuantity(5.1, StandardUnits.ACTIVE_POWER_RESULT)
Quantity<Power> pMin = Quantities.getQuantity(-6, StandardUnits.ACTIVE_POWER_RESULT)
Quantity<Power> pMax = Quantities.getQuantity(6, StandardUnits.ACTIVE_POWER_RESULT)
def validResult = new FlexOptionsResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, pReference, pMin, pMax)
def expectedResults = [
uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
time : '2020-01-30T17:26:44Z[UTC]',
pMax : '6.0',
pMin : '-6.0',
pReference: '5.1',
]
when:
def validProcessedElement = sysPartResProcessor.handleEntity(validResult)
then:
validProcessedElement.present
validProcessedElement.get() == expectedResults
}
@Shared
def expectedLineResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
iAMag : '100.0',
iAAng : '45.0',
iBMag : '150.0',
iBAng : '30.0',
time : '2020-01-30T17:26:44Z[UTC]']
@Shared
def expectedTrafo2WResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
iAMag : '100.0',
iAAng : '45.0',
iBMag : '150.0',
iBAng : '30.0',
tapPos : '5',
time : '2020-01-30T17:26:44Z[UTC]']
@Shared
def expectedTrafo3WResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
iAMag : '100.0',
iAAng : '45.0',
iBMag : '150.0',
iBAng : '30.0',
iCMag : '300.0',
iCAng : '70.0',
tapPos : '5',
time : '2020-01-30T17:26:44Z[UTC]']
@Shared
def expectedSwitchResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
closed : 'true',
time : '2020-01-30T17:26:44Z[UTC]']
@Shared
Quantity<ElectricCurrent> iAMag = Quantities.getQuantity(100, StandardUnits.ELECTRIC_CURRENT_MAGNITUDE)
@Shared
Quantity<Angle> iAAng = Quantities.getQuantity(45, StandardUnits.ELECTRIC_CURRENT_ANGLE)
@Shared
Quantity<ElectricCurrent> iBMag = Quantities.getQuantity(150, StandardUnits.ELECTRIC_CURRENT_MAGNITUDE)
@Shared
Quantity<Angle> iBAng = Quantities.getQuantity(30, StandardUnits.ELECTRIC_CURRENT_ANGLE)
@Shared
Quantity<ElectricCurrent> iCMag = Quantities.getQuantity(300, StandardUnits.ELECTRIC_CURRENT_MAGNITUDE)
@Shared
Quantity<Angle> iCAng = Quantities.getQuantity(70, StandardUnits.ELECTRIC_CURRENT_ANGLE)
@Shared
int tapPos = 5
@Shared
boolean closed = true
def "A ResultEntityProcessor should de-serialize all ConnectorResults correctly"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(modelClass)
def validResult = validConnectorResult
when:
def validProcessedElement = sysPartResProcessor.handleEntity(validResult)
then:
validProcessedElement.present
validProcessedElement.get() == expectedResults
where:
modelClass | validConnectorResult || expectedResults
LineResult | new LineResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, iAMag, iAAng, iBMag, iBAng) || expectedLineResults
SwitchResult | new SwitchResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, closed) || expectedSwitchResults
Transformer2WResult | new Transformer2WResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, iAMag, iAAng, iBMag, iBAng, tapPos) || expectedTrafo2WResults
Transformer3WResult | new Transformer3WResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, iAMag, iAAng, iBMag, iBAng, iCMag, iCAng, tapPos) || expectedTrafo3WResults
}
def "A ResultEntityProcessor should de-serialize a CylindricalStorageResult correctly"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(CylindricalStorageResult)
Quantity<Power> qDot = Quantities.getQuantity(2, StandardUnits.Q_DOT_RESULT)
Quantity<Energy> energy = Quantities.getQuantity(3, StandardUnits.ENERGY_RESULT)
Quantity<Dimensionless> fillLevel = Quantities.getQuantity(20, Units.PERCENT)
def validResult = new CylindricalStorageResult(uuid, ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputModel, energy, qDot, fillLevel)
def expectedResults = [uuid : '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
energy : '3.0',
fillLevel : '20.0',
inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52',
qDot : '2.0',
time : '2020-01-30T17:26:44Z[UTC]']
when:
def validProcessedElement = sysPartResProcessor.handleEntity(validResult)
then:
validProcessedElement.present
validProcessedElement.get() == expectedResults
}
def "A ResultEntityProcessor should throw an EntityProcessorException when it receives an entity result that is not eligible"() {
given:
def sysPartResProcessor = new ResultEntityProcessor(ResultEntityProcessor.eligibleEntityClasses.get(0))
def invalidClassResult = new InvalidTestResult(ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), uuid)
when:
sysPartResProcessor.handleEntity(invalidClassResult)
then:
EntityProcessorException exception = thrown()
exception.message == "Cannot process InvalidTestResult.class with this EntityProcessor. " +
"Please either provide an element of LoadResult.class or create a new processor for InvalidTestResult.class!"
}
def "The list of eligible entity classes for a ResultEntityProcessor should be valid"() {
given:
int noOfElements = 19 // number of all currently implemented entity results
expect:
ResultEntityProcessor.eligibleEntityClasses.size() == noOfElements
}
def "ResultEntityProcessor should throw an exception if an invalid class is passed into the constructor"() {
when:
new ResultEntityProcessor(InvalidTestResult)
then:
thrown(EntityProcessorException)
}
private static class InvalidTestResult extends ResultEntity {
InvalidTestResult(ZonedDateTime time, UUID inputModel) {
super(time, inputModel)
}
InvalidTestResult(UUID uuid, ZonedDateTime time, UUID inputModel) {
super(uuid, time, inputModel)
}
}
}