2
2
3
3
import de .rwth .idsg .steve .utils .StressTester ;
4
4
import de .rwth .idsg .steve .utils .__DatabasePreparer__ ;
5
- import lombok .extern .slf4j .Slf4j ;
6
5
import ocpp .cs ._2015 ._10 .AuthorizationStatus ;
7
6
import ocpp .cs ._2015 ._10 .AuthorizeRequest ;
8
7
import ocpp .cs ._2015 ._10 .AuthorizeResponse ;
9
8
import ocpp .cs ._2015 ._10 .BootNotificationRequest ;
10
9
import ocpp .cs ._2015 ._10 .BootNotificationResponse ;
11
10
import ocpp .cs ._2015 ._10 .CentralSystemService ;
11
+ import ocpp .cs ._2015 ._10 .ChargePointErrorCode ;
12
+ import ocpp .cs ._2015 ._10 .ChargePointStatus ;
13
+ import ocpp .cs ._2015 ._10 .HeartbeatRequest ;
14
+ import ocpp .cs ._2015 ._10 .HeartbeatResponse ;
15
+ import ocpp .cs ._2015 ._10 .MeterValue ;
16
+ import ocpp .cs ._2015 ._10 .MeterValuesRequest ;
17
+ import ocpp .cs ._2015 ._10 .MeterValuesResponse ;
12
18
import ocpp .cs ._2015 ._10 .RegistrationStatus ;
13
- import org .junit .After ;
14
- import org .junit .AfterClass ;
19
+ import ocpp .cs ._2015 ._10 .SampledValue ;
20
+ import ocpp .cs ._2015 ._10 .StartTransactionRequest ;
21
+ import ocpp .cs ._2015 ._10 .StartTransactionResponse ;
22
+ import ocpp .cs ._2015 ._10 .StatusNotificationRequest ;
23
+ import ocpp .cs ._2015 ._10 .StatusNotificationResponse ;
24
+ import ocpp .cs ._2015 ._10 .StopTransactionRequest ;
25
+ import ocpp .cs ._2015 ._10 .StopTransactionResponse ;
26
+ import org .joda .time .DateTime ;
15
27
import org .junit .Assert ;
16
- import org .junit .Before ;
17
- import org .junit .BeforeClass ;
18
- import org .junit .Test ;
28
+
29
+ import java .util .ArrayList ;
30
+ import java .util .Collections ;
31
+ import java .util .List ;
32
+ import java .util .concurrent .ThreadLocalRandom ;
19
33
20
34
import static de .rwth .idsg .steve .utils .Helpers .getForOcpp16 ;
21
35
import static de .rwth .idsg .steve .utils .Helpers .getPath ;
22
36
import static de .rwth .idsg .steve .utils .Helpers .getRandomString ;
37
+ import static de .rwth .idsg .steve .utils .Helpers .getRandomStrings ;
23
38
24
39
/**
25
40
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
26
41
* @since 18.04.2018
27
42
*/
28
- @ Slf4j
29
43
public class StressTestSoapOCPP16 {
30
44
31
- private static final String REGISTERED_CHARGE_BOX_ID = __DatabasePreparer__ .getRegisteredChargeBoxId ();
45
+ // higher values -> more stress
46
+ //
47
+ private static final int THREAD_COUNT = 50 ;
48
+ private static final int REPEAT_COUNT_PER_THREAD = 50 ;
49
+
50
+ // lower values -> more stress
51
+ //
52
+ // reason: these only specify the size of the values "bag" from which a test picks a value randomly. if there is
53
+ // less values to pick from, it is more likely that tests will use the same value at the same time. this produces
54
+ // more overhead for steve (especially db) when multiple threads "fight" for inserting/updating a db row/cell.
55
+ //
56
+ private static final int ID_TAG_COUNT = 50 ;
57
+ private static final int CHARGE_BOX_COUNT = 100 ;
58
+ private static final int CONNECTOR_COUNT_PER_CHARGE_BOX = 25 ;
32
59
33
60
private static final String path = getPath ();
34
- private static Application app ;
35
61
36
- @ BeforeClass
37
- public static void initClass () throws Exception {
62
+ public static void main (String [] args ) throws Exception {
63
+ new StressTestSoapOCPP16 ().attack ();
64
+ }
65
+
66
+ private void attack () throws Exception {
38
67
Assert .assertEquals (ApplicationProfile .TEST , SteveConfiguration .CONFIG .getProfile ());
39
68
Assert .assertTrue (SteveConfiguration .CONFIG .getOcpp ().isAutoRegisterUnknownStations ());
40
69
41
- app = new Application ();
42
- app .start ();
43
- }
70
+ __DatabasePreparer__ .prepare ();
44
71
45
- @ AfterClass
46
- public static void destroyClass () throws Exception {
47
- if (app != null ) {
48
- app .stop ();
72
+ Application app = new Application ();
73
+ try {
74
+ app .start ();
75
+ attackInternal ();
76
+ } finally {
77
+ try {
78
+ app .stop ();
79
+ } finally {
80
+ __DatabasePreparer__ .cleanUp ();
81
+ }
49
82
}
50
83
}
51
84
52
- @ Before
53
- public void init () {
54
- __DatabasePreparer__ .prepare ();
55
- }
85
+ private static void attackInternal () throws Exception {
86
+ final List <String > idTags = getRandomStrings (ID_TAG_COUNT );
87
+ final List <String > chargeBoxIds = getRandomStrings (CHARGE_BOX_COUNT );
56
88
57
- @ After
58
- public void destroy () {
59
- __DatabasePreparer__ .cleanUp ();
60
- }
89
+ StressTester tester = new StressTester (THREAD_COUNT , REPEAT_COUNT_PER_THREAD );
61
90
62
- @ Test
63
- public void testBootNotification () throws Exception {
64
- StressTester tester = new StressTester ( 50 , 5 );
91
+ tester . test (() -> {
92
+ CentralSystemService client = getForOcpp16 ( path );
93
+ ThreadLocalRandom localRandom = ThreadLocalRandom . current ( );
65
94
66
- CentralSystemService client = getForOcpp16 (path );
95
+ String idTag = idTags .get (localRandom .nextInt (idTags .size ()));
96
+ String chargeBoxId = chargeBoxIds .get (localRandom .nextInt (chargeBoxIds .size ()));
97
+ int connectorId = localRandom .nextInt (1 , CONNECTOR_COUNT_PER_CHARGE_BOX + 1 );
67
98
68
- tester .test (() -> {
99
+ int transactionStart = localRandom .nextInt (0 , Integer .MAX_VALUE );
100
+ int transactionStop = localRandom .nextInt (transactionStart + 1 , Integer .MAX_VALUE );
101
+
102
+ // to insert chargeBoxId into db
69
103
BootNotificationResponse boot = client .bootNotification (
70
104
new BootNotificationRequest ()
71
105
.withChargePointVendor (getRandomString ())
72
106
.withChargePointModel (getRandomString ()),
73
- getRandomString () );
107
+ chargeBoxId );
74
108
Assert .assertEquals (RegistrationStatus .ACCEPTED , boot .getStatus ());
109
+
110
+ HeartbeatResponse heartbeat = client .heartbeat (
111
+ new HeartbeatRequest (),
112
+ chargeBoxId
113
+ );
114
+ Assert .assertNotNull (heartbeat );
115
+
116
+ for (int i = 0 ; i <= CONNECTOR_COUNT_PER_CHARGE_BOX ; i ++) {
117
+ StatusNotificationResponse status = client .statusNotification (
118
+ new StatusNotificationRequest ()
119
+ .withErrorCode (ChargePointErrorCode .NO_ERROR )
120
+ .withStatus (ChargePointStatus .AVAILABLE )
121
+ .withConnectorId (i )
122
+ .withTimestamp (DateTime .now ()),
123
+ chargeBoxId
124
+ );
125
+ Assert .assertNotNull (status );
126
+ }
127
+
128
+ AuthorizeResponse auth = client .authorize (
129
+ new AuthorizeRequest ().withIdTag (idTag ),
130
+ chargeBoxId
131
+ );
132
+ Assert .assertNotEquals (AuthorizationStatus .ACCEPTED , auth .getIdTagInfo ().getStatus ());
133
+
134
+ StartTransactionResponse start = client .startTransaction (
135
+ new StartTransactionRequest ()
136
+ .withConnectorId (connectorId )
137
+ .withIdTag (idTag )
138
+ .withTimestamp (DateTime .now ())
139
+ .withMeterStart (transactionStart ),
140
+ chargeBoxId
141
+ );
142
+ Assert .assertNotNull (start );
143
+
144
+ StatusNotificationResponse statusStart = client .statusNotification (
145
+ new StatusNotificationRequest ()
146
+ .withErrorCode (ChargePointErrorCode .NO_ERROR )
147
+ .withStatus (ChargePointStatus .CHARGING )
148
+ .withConnectorId (connectorId )
149
+ .withTimestamp (DateTime .now ()),
150
+ chargeBoxId
151
+ );
152
+ Assert .assertNotNull (statusStart );
153
+
154
+ MeterValuesResponse meter = client .meterValues (
155
+ new MeterValuesRequest ()
156
+ .withConnectorId (connectorId )
157
+ .withTransactionId (start .getTransactionId ())
158
+ .withMeterValue (getMeterValues (transactionStart , transactionStop )),
159
+ chargeBoxId
160
+ );
161
+ Assert .assertNotNull (meter );
162
+
163
+ StopTransactionResponse stop = client .stopTransaction (
164
+ new StopTransactionRequest ()
165
+ .withTransactionId (start .getTransactionId ())
166
+ .withTimestamp (DateTime .now ())
167
+ .withIdTag (idTag )
168
+ .withMeterStop (transactionStop ),
169
+ chargeBoxId
170
+ );
171
+ Assert .assertNotNull (stop );
172
+
173
+ StatusNotificationResponse statusStop = client .statusNotification (
174
+ new StatusNotificationRequest ()
175
+ .withErrorCode (ChargePointErrorCode .NO_ERROR )
176
+ .withStatus (ChargePointStatus .AVAILABLE )
177
+ .withConnectorId (connectorId )
178
+ .withTimestamp (DateTime .now ()),
179
+ chargeBoxId
180
+ );
181
+ Assert .assertNotNull (statusStop );
75
182
});
76
183
77
184
tester .shutDown ();
78
185
}
79
186
80
- @ Test
81
- public void testAuthorize () throws Exception {
82
- StressTester tester = new StressTester (100 , 10 );
83
-
84
- CentralSystemService client = getForOcpp16 (path );
187
+ private static List <MeterValue > getMeterValues (int transactionStart , int transactionStop ) {
188
+ final int size = 4 ;
189
+ int delta = (transactionStop - transactionStart ) / size ;
190
+ if (delta == 0 ) {
191
+ return Collections .emptyList ();
192
+ }
85
193
86
- tester .test (() -> {
87
- AuthorizeResponse auth = client .authorize (
88
- new AuthorizeRequest ().withIdTag (getRandomString ()),
89
- REGISTERED_CHARGE_BOX_ID );
90
- Assert .assertEquals (AuthorizationStatus .INVALID , auth .getIdTagInfo ().getStatus ());
91
- });
194
+ List <MeterValue > list = new ArrayList <>(size );
195
+ for (int i = 0 ; i < size ; i ++) {
196
+ int meterValue = transactionStart + delta * (i + 1 );
197
+ list .add (createMeterValue (meterValue ));
198
+ }
199
+ return list ;
200
+ }
92
201
93
- tester .shutDown ();
202
+ private static MeterValue createMeterValue (int val ) {
203
+ return new MeterValue ().withTimestamp (DateTime .now ())
204
+ .withSampledValue (new SampledValue ().withValue (Integer .toString (val )));
94
205
}
95
206
96
- }
207
+ }
0 commit comments