1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.loadtest;
14
15 import java.beans.PropertyChangeEvent;
16 import java.beans.PropertyChangeListener;
17 import java.util.ArrayList;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21
22 import org.apache.log4j.Logger;
23
24 import com.eviware.soapui.config.LoadStrategyConfig;
25 import com.eviware.soapui.config.LoadTestAssertionConfig;
26 import com.eviware.soapui.config.LoadTestConfig;
27 import com.eviware.soapui.config.LoadTestLimitTypesConfig;
28 import com.eviware.soapui.config.LoadTestLimitTypesConfig.Enum;
29 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
30 import com.eviware.soapui.impl.wsdl.loadtest.assertions.AbstractLoadTestAssertion;
31 import com.eviware.soapui.impl.wsdl.loadtest.assertions.LoadTestAssertionRegistry;
32 import com.eviware.soapui.impl.wsdl.loadtest.data.LoadTestStatistics;
33 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
34 import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogErrorEntry;
35 import com.eviware.soapui.impl.wsdl.loadtest.strategy.BurstLoadStrategy;
36 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategy;
37 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyFactory;
38 import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyRegistry;
39 import com.eviware.soapui.impl.wsdl.loadtest.strategy.SimpleLoadStrategy;
40 import com.eviware.soapui.impl.wsdl.support.Configurable;
41 import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
42 import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
43 import com.eviware.soapui.model.testsuite.LoadTest;
44 import com.eviware.soapui.model.testsuite.LoadTestRunContext;
45 import com.eviware.soapui.model.testsuite.LoadTestRunListener;
46 import com.eviware.soapui.model.testsuite.LoadTestRunner;
47 import com.eviware.soapui.model.testsuite.TestRunContext;
48 import com.eviware.soapui.model.testsuite.TestRunner;
49 import com.eviware.soapui.model.testsuite.TestStepResult;
50 import com.eviware.soapui.model.testsuite.LoadTestRunner.Status;
51
52 /***
53 * TestCase implementation for LoadTests
54 *
55 * @todo add assertionFailed event to LoadTestListener
56 * @todo create and return LoadTestAssertionResult from load-test assertions
57 *
58 * @author Ole.Matzura
59 */
60
61 public class WsdlLoadTest extends AbstractWsdlModelItem<LoadTestConfig> implements LoadTest
62 {
63 public final static String THREADCOUNT_PROPERTY = WsdlLoadTest.class.getName() + "@threadcount";
64 public final static String STARTDELAY_PROPERTY = WsdlLoadTest.class.getName() + "@startdelay";
65 public final static String TESTLIMIT_PROPERTY = WsdlLoadTest.class.getName() + "@testlimit";
66 public final static String HISTORYLIMIT_PROPERTY = WsdlLoadTest.class.getName() + "@historylimit";
67 public final static String LIMITTYPE_PROPERRY = WsdlLoadTest.class.getName() + "@limittype";
68 public final static String SAMPLEINTERVAL_PROPERRY = WsdlLoadTest.class.getName() + "@sample-interval";
69
70 private final static Logger logger = Logger.getLogger( WsdlLoadTest.class );
71 private InternalTestRunListener internalTestRunListener = new InternalTestRunListener();
72
73 private WsdlTestCase testCase;
74 private LoadTestStatistics statisticsModel;
75 private LoadStrategy loadStrategy = new BurstLoadStrategy();
76 private LoadTestLog loadTestLog;
77
78 private LoadStrategyConfigurationChangeListener loadStrategyListener = new LoadStrategyConfigurationChangeListener();
79 private List<LoadTestAssertion> assertions = new ArrayList<LoadTestAssertion>();
80 private ConfigurationChangePropertyListener configurationChangeListener = new ConfigurationChangePropertyListener();
81 private Set<LoadTestListener> listeners = new HashSet<LoadTestListener>();
82 private Set<LoadTestRunListener> runListeners = new HashSet<LoadTestRunListener>();
83 private WsdlLoadTestRunner runner;
84
85 public WsdlLoadTest(WsdlTestCase testCase, LoadTestConfig config )
86 {
87 super( config, testCase, "/loadTest.gif" );
88
89 this.testCase = testCase;
90
91 if( getConfig().getThreadCount() < 1 )
92 getConfig().setThreadCount( 5 );
93
94 if( getConfig().getLimitType() == null )
95 {
96 getConfig().setLimitType( LoadTestLimitTypesConfig.TIME );
97 getConfig().setTestLimit( 60 );
98 }
99
100 if( !getConfig().isSetHistoryLimit() )
101 {
102 getConfig().setHistoryLimit( -1 );
103 }
104
105 addLoadTestRunListener( internalTestRunListener );
106
107 LoadStrategyConfig ls = getConfig().getLoadStrategy();
108 if( ls == null )
109 {
110 ls = getConfig().addNewLoadStrategy();
111 ls.setType( SimpleLoadStrategy.STRATEGY_TYPE );
112 }
113
114 LoadStrategyFactory factory = LoadStrategyRegistry.getInstance().getFactory( ls.getType() );
115 if( factory == null )
116 {
117 ls.setType( SimpleLoadStrategy.STRATEGY_TYPE );
118 factory = LoadStrategyRegistry.getInstance().getFactory( ls.getType() );
119 }
120
121 loadStrategy = factory.build( ls.getConfig() );
122 loadStrategy.addConfigurationChangeListener( loadStrategyListener );
123
124 addLoadTestRunListener( loadStrategy );
125
126 statisticsModel = new LoadTestStatistics( this );
127
128 if( getConfig().xgetSampleInterval() == null )
129 setSampleInterval( LoadTestStatistics.DEFAULT_SAMPLE_INTERVAL );
130
131 statisticsModel.setUpdateFrequency( getSampleInterval() );
132
133 List<LoadTestAssertionConfig> assertionList = getConfig().getAssertionList();
134 for( LoadTestAssertionConfig assertionConfig : assertionList )
135 {
136 AbstractLoadTestAssertion assertion = LoadTestAssertionRegistry.buildAssertion( assertionConfig, this );
137 if( assertion != null )
138 {
139 assertions.add( assertion);
140 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
141 }
142 else
143 {
144 logger.warn( "Failed to build LoadTestAssertion from getConfig() [" + assertionConfig + "]" );
145 }
146 }
147
148 if( getConfig().xgetResetStatisticsOnThreadCountChange() == null )
149 getConfig().setResetStatisticsOnThreadCountChange( true );
150
151 if( getConfig().xgetCalculateTPSOnTimePassed() == null )
152 getConfig().setCalculateTPSOnTimePassed( false );
153
154 loadTestLog = new LoadTestLog( this );
155 }
156
157 public LoadTestStatistics getStatisticsModel()
158 {
159 return statisticsModel;
160 }
161
162 public long getThreadCount()
163 {
164 return getConfig().getThreadCount();
165 }
166
167 public void setThreadCount( long threadCount )
168 {
169 if( threadCount < 1 || threadCount == getThreadCount() )
170 return;
171
172 long oldCount = getThreadCount();
173 getConfig().setThreadCount( (int) threadCount );
174 notifyPropertyChanged( THREADCOUNT_PROPERTY, oldCount, threadCount );
175 }
176
177 public boolean getResetStatisticsOnThreadCountChange()
178 {
179 return getConfig().getResetStatisticsOnThreadCountChange();
180 }
181
182 public void setResetStatisticsOnThreadCountChange( boolean value )
183 {
184 getConfig().setResetStatisticsOnThreadCountChange( value );
185 }
186
187 public boolean getCalculateTPSOnTimePassed()
188 {
189 return getConfig().getCalculateTPSOnTimePassed();
190 }
191
192 public void setCalculateTPSOnTimePassed( boolean value )
193 {
194 getConfig().setCalculateTPSOnTimePassed( value );
195 }
196
197 public int getStartDelay()
198 {
199 return getConfig().getStartDelay();
200 }
201
202 public void setStartDelay( int startDelay )
203 {
204 if( startDelay < 0 )
205 return;
206
207 int oldDelay = getStartDelay();
208 getConfig().setStartDelay( startDelay );
209 notifyPropertyChanged( STARTDELAY_PROPERTY, oldDelay, startDelay );
210 }
211
212 public long getHistoryLimit()
213 {
214 return getConfig().getHistoryLimit();
215 }
216
217 public void setHistoryLimit( long historyLimit )
218 {
219 long oldLimit = getHistoryLimit();
220 getConfig().setHistoryLimit( historyLimit );
221 if( historyLimit == 0 )
222
223
224 notifyPropertyChanged( HISTORYLIMIT_PROPERTY, oldLimit, historyLimit );
225 }
226
227 public long getTestLimit()
228 {
229 return getConfig().getTestLimit();
230 }
231
232 public void setTestLimit( long testLimit )
233 {
234 if( testLimit < 0 )
235 return;
236
237 long oldLimit = getTestLimit();
238 getConfig().setTestLimit( testLimit );
239 notifyPropertyChanged( TESTLIMIT_PROPERTY, oldLimit, testLimit );
240 }
241
242 public long getSampleInterval()
243 {
244 return getConfig().getSampleInterval();
245 }
246
247 public void setSampleInterval( int sampleInterval )
248 {
249 if( sampleInterval < 0 )
250 return;
251
252 long oldInterval = getSampleInterval();
253 getConfig().setSampleInterval( sampleInterval );
254
255 statisticsModel.setUpdateFrequency( sampleInterval );
256
257 notifyPropertyChanged( TESTLIMIT_PROPERTY, oldInterval, sampleInterval );
258 }
259
260 public Enum getLimitType()
261 {
262 return getConfig().getLimitType();
263 }
264
265 public void setLimitType( Enum limitType )
266 {
267 if( limitType == null )
268 return;
269
270 Enum oldType = getLimitType();
271 getConfig().setLimitType( limitType );
272 notifyPropertyChanged( LIMITTYPE_PROPERRY, oldType, limitType );
273 }
274
275 public WsdlTestCase getTestCase()
276 {
277 return testCase;
278 }
279
280 public synchronized WsdlLoadTestRunner run()
281 {
282 getStatisticsModel().reset();
283 if( runner != null && runner.getStatus() == Status.RUNNING )
284 return null;
285
286 runner = new WsdlLoadTestRunner( this );
287 runner.start();
288 return runner;
289 }
290
291 private class InternalTestRunListener extends LoadTestRunListenerAdapter
292 {
293 public void afterTestCase(LoadTestRunner loadTestRunner, LoadTestRunContext context, TestRunner testRunner, TestRunContext runContext)
294 {
295 if( !assertions.isEmpty() )
296 {
297 for( LoadTestAssertion assertion : assertions )
298 {
299 String error = assertion.assertResults( loadTestRunner, context, testRunner, runContext );
300 if( error != null )
301 {
302 loadTestLog.addEntry( new LoadTestLogErrorEntry( assertion.getName(), error, assertion.getIcon() ));
303 statisticsModel.addError( LoadTestStatistics.TOTAL );
304 }
305 }
306 }
307 }
308
309 public void afterTestStep(LoadTestRunner loadTestRunner, LoadTestRunContext context, TestRunner testRunner, TestRunContext runContext, TestStepResult result)
310 {
311 if( !assertions.isEmpty() )
312 {
313 boolean added = false;
314
315 for( LoadTestAssertion assertion : assertions )
316 {
317 String error = assertion.assertResult( loadTestRunner, context, result, testRunner, runContext );
318 if( error != null )
319 {
320 int indexOfTestStep = testRunner.getTestCase().getIndexOfTestStep( result.getTestStep() );
321
322 loadTestLog.addEntry( new LoadTestLogErrorEntry( assertion.getName(), error, result, assertion.getIcon() ));
323 statisticsModel.addError( indexOfTestStep);
324
325 added = true;
326 }
327 }
328
329
330 if( !added )
331 {
332 result.discard();
333 }
334 }
335 else result.discard();
336 }
337 }
338
339 public LoadStrategy getLoadStrategy()
340 {
341 return loadStrategy;
342 }
343
344 public void setLoadStrategy( LoadStrategy loadStrategy )
345 {
346 this.loadStrategy.removeConfigurationChangeListener( loadStrategyListener );
347 removeLoadTestRunListener( this.loadStrategy );
348
349 this.loadStrategy = loadStrategy;
350 this.loadStrategy.addConfigurationChangeListener( loadStrategyListener );
351 addLoadTestRunListener( this.loadStrategy );
352
353 getConfig().getLoadStrategy().setType( loadStrategy.getType() );
354 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
355 }
356
357 private class LoadStrategyConfigurationChangeListener implements PropertyChangeListener
358 {
359 public void propertyChange(PropertyChangeEvent evt)
360 {
361 getConfig().getLoadStrategy().setConfig( loadStrategy.getConfig() );
362 }
363 }
364
365 public LoadTestAssertion addAssertion( String type, String targetStep, boolean showConfig )
366 {
367 LoadTestAssertion assertion = LoadTestAssertionRegistry.createAssertion( type, this );
368 assertion.setTargetStep( targetStep );
369
370 if( assertion instanceof Configurable && showConfig )
371 {
372 if( !((Configurable)assertion).configure() )
373 return null;
374 }
375
376 assertions.add( assertion );
377
378 getConfig().addNewAssertion().set( assertion.getConfiguration() );
379 assertion.addPropertyChangeListener( LoadTestAssertion.CONFIGURATION_PROPERTY, configurationChangeListener );
380 fireAssertionAdded( assertion );
381
382 return assertion;
383 }
384
385 public void removeAssertion( LoadTestAssertion assertion)
386 {
387 int ix = assertions.indexOf( assertion );
388 if( ix >= 0 )
389 {
390 try
391 {
392 assertions.remove( ix );
393 fireAssertionRemoved(assertion);
394 }
395 finally
396 {
397 assertion.removePropertyChangeListener( configurationChangeListener );
398 assertion.release();
399 getConfig().removeAssertion( ix );
400 }
401 }
402 }
403
404 private void fireAssertionRemoved(LoadTestAssertion assertion)
405 {
406 if( !listeners.isEmpty() )
407 {
408 LoadTestListener[] l = listeners.toArray( new LoadTestListener[listeners.size()] );
409 for( LoadTestListener listener : l )
410 {
411 listener.assertionRemoved( assertion );
412 }
413 }
414 }
415
416 private void fireAssertionAdded(LoadTestAssertion assertion)
417 {
418 if( !listeners.isEmpty() )
419 {
420 LoadTestListener[] l = listeners.toArray( new LoadTestListener[listeners.size()] );
421 for( LoadTestListener listener : l )
422 {
423 listener.assertionAdded( assertion );
424 }
425 }
426 }
427
428 public int getAssertionCount()
429 {
430 return assertions.size();
431 }
432
433 public LoadTestAssertion getAssertionAt( int index )
434 {
435 return assertions.get( index );
436 }
437
438 private class ConfigurationChangePropertyListener implements PropertyChangeListener
439 {
440 public void propertyChange(PropertyChangeEvent evt)
441 {
442 int ix = assertions.indexOf( evt.getSource() );
443 if( ix >= 0 )
444 {
445 getConfig().getAssertionArray( ix ).set( assertions.get( ix ).getConfiguration() );
446 }
447 }
448 }
449
450 public LoadTestLog getLoadTestLog()
451 {
452 return loadTestLog;
453 }
454
455 public List<LoadTestAssertion> getAssertionList()
456 {
457 return assertions;
458 }
459
460 public void addLoadTestListener( LoadTestListener listener )
461 {
462 listeners.add( listener );
463 }
464
465 public void removeLoadTestListener( LoadTestListener listener )
466 {
467 listeners.remove( listener );
468 }
469
470 public void addLoadTestRunListener(LoadTestRunListener listener)
471 {
472 runListeners.add( listener );
473 }
474
475 public void removeLoadTestRunListener(LoadTestRunListener listener)
476 {
477 runListeners.remove( listener );
478 }
479
480 public LoadTestRunListener [] getLoadTestRunListeners()
481 {
482 return runListeners.toArray( new LoadTestRunListener[runListeners.size()] );
483 }
484
485 /***
486 * Release internal objects so they can remove listeners
487 */
488
489 public void release()
490 {
491 super.release();
492
493 statisticsModel.release();
494 loadTestLog.release();
495
496 for( LoadTestAssertion assertion : assertions )
497 assertion.release();
498 }
499
500 public boolean isRunning()
501 {
502 return runner != null && runner.getStatus() == LoadTestRunner.Status.RUNNING;
503 }
504
505 public WsdlLoadTestRunner getRunner()
506 {
507 return runner;
508 }
509
510 public void resetConfigOnMove( LoadTestConfig config )
511 {
512 setConfig( config );
513
514 loadStrategy.updateConfig( config.getLoadStrategy().getConfig() );
515
516 List<LoadTestAssertionConfig> assertionList = config.getAssertionList();
517 for( int c = 0; c < assertionList.size(); c++ )
518 {
519 assertions.get( c ).updateConfiguration( assertionList.get( c ) );
520 }
521 }
522 }