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